Skip to content

Commit

Permalink
Refactor beneficiary field mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
samnang committed Jan 13, 2025
1 parent b25c721 commit 454566f
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 36 deletions.
2 changes: 1 addition & 1 deletion app/models/aggregate_data_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def apply(scope)
private

def query_scope(scope)
joins_with = group_by_fields.pluck(:relation) + filter_fields.keys.pluck(:relation)
joins_with = group_by_fields.map(&:relation) + filter_fields.map { |f, _| f.relation }
joins_with = joins_with.compact_blank.uniq
scope = scope.joins(*joins_with) if joins_with.any?
scope
Expand Down
33 changes: 33 additions & 0 deletions app/models/beneficiary_field.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class BeneficiaryField
def initialize(name:, column:, relation: nil)
@name = name
@column = column
@relation = relation
end


attr_reader :name, :column, :relation

def self.all
@all ||= [
self.new(name: "status", column: "status"),
self.new(name: "gender", column: "gender"),
self.new(name: "date_of_birth", column: "date_of_birth"),
self.new(name: "language_code", column: "language_code"),
self.new(name: "iso_country_code", column: "iso_country_code"),
self.new(name: "address.iso_region_code", column: "beneficiary_addresses.iso_region_code", relation: :addresses),
self.new(name: "address.administrative_division_level_2_code", column: "beneficiary_addresses.administrative_division_level_2_code", relation: :addresses),
self.new(name: "address.administrative_division_level_2_name", column: "beneficiary_addresses.administrative_division_level_2_name", relation: :addresses),
self.new(name: "address.administrative_division_level_3_code", column: "beneficiary_addresses.administrative_division_level_3_code", relation: :addresses),
self.new(name: "address.administrative_division_level_3_name", column: "beneficiary_addresses.administrative_division_level_3_name", relation: :addresses),
self.new(name: "address.administrative_division_level_4_code", column: "beneficiary_addresses.administrative_division_level_4_code", relation: :addresses),
self.new(name: "address.administrative_division_level_4_name", column: "beneficiary_addresses.administrative_division_level_4_name", relation: :addresses)
]
end

def self.find(name)
result = all.find { |f| f.name == name }
raise ArgumentError, "Unknown field #{name}" if result.nil?
result
end
end
20 changes: 2 additions & 18 deletions app/request_schemas/v1/beneficiary_stats_request_schema.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
module V1
class BeneficiaryStatsRequestSchema < ApplicationRequestSchema
Field = Struct.new(:name, :column, :relation, keyword_init: true)
FIELDS = {
"status" => Field.new(name: "status", column: "status"),
"gender" => Field.new(name: "gender", column: "gender"),
"date_of_birth" => Field.new(name: "date_of_birth", column: "date_of_birth"),
"language_code" => Field.new(name: "language_code", column: "language_code"),
"iso_country_code" => Field.new(name: "iso_country_code", column: "iso_country_code"),
"address.iso_region_code" => Field.new(name: "address.iso_region_code", column: "beneficiary_addresses.iso_region_code", relation: :addresses),
"address.administrative_division_level_2_code" => Field.new(name: "address.administrative_division_level_2_code", column: "beneficiary_addresses.administrative_division_level_2_code", relation: :addresses),
"address.administrative_division_level_2_name" => Field.new(name: "address.administrative_division_level_2_name", column: "beneficiary_addresses.administrative_division_level_2_name", relation: :addresses),
"address.administrative_division_level_3_code" => Field.new(name: "address.administrative_division_level_3_code", column: "beneficiary_addresses.administrative_division_level_3_code", relation: :addresses),
"address.administrative_division_level_3_name" => Field.new(name: "address.administrative_division_level_3_name", column: "beneficiary_addresses.administrative_division_level_3_name", relation: :addresses),
"address.administrative_division_level_4_code" => Field.new(name: "address.administrative_division_level_4_code", column: "beneficiary_addresses.administrative_division_level_4_code", relation: :addresses),
"address.administrative_division_level_4_name" => Field.new(name: "address.administrative_division_level_4_name", column: "beneficiary_addresses.administrative_division_level_4_name", relation: :addresses)
}.freeze

GROUPS = [
"gender",
"language_code",
Expand Down Expand Up @@ -68,11 +52,11 @@ def output
result = super

result[:filter_fields] = result.fetch(:filter, {}).each_with_object({}) do |(filter, value), filters|
filters[FIELDS.fetch(filter.to_s)] = value
filters[BeneficiaryField.find(filter.to_s)] = value
end

result[:group_by_fields] = result[:group_by].map do |group|
FIELDS.fetch(group)
BeneficiaryField.find(group)
end

result
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
require "rails_helper"

RSpec.describe "AgreegateDataQuery", type: :model do
RSpec.describe AggregateDataQuery, type: :model do
it "return results with a simple group by field" do
create_list(:beneficiary, 2, gender: "M")
create_list(:beneficiary, 3, gender: "F")

result = AggregateDataQuery.new(
group_by_fields: [
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("gender")
BeneficiaryField.find("gender")
],
).apply(Contact.all)

Expand Down Expand Up @@ -35,9 +35,9 @@

result = AggregateDataQuery.new(
group_by_fields: [
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("iso_country_code"),
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("address.iso_region_code"),
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("address.administrative_division_level_2_code")
BeneficiaryField.find("iso_country_code"),
BeneficiaryField.find("address.iso_region_code"),
BeneficiaryField.find("address.administrative_division_level_2_code")
],
).apply(Contact.all)

Expand Down Expand Up @@ -72,12 +72,12 @@

result = AggregateDataQuery.new(
filter_fields: {
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("address.iso_region_code") => "KH-12"
BeneficiaryField.find("address.iso_region_code") => "KH-12"
},
group_by_fields: [
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("iso_country_code"),
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("address.iso_region_code"),
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("address.administrative_division_level_2_code")
BeneficiaryField.find("iso_country_code"),
BeneficiaryField.find("address.iso_region_code"),
BeneficiaryField.find("address.administrative_division_level_2_code")
],
).apply(Contact.all)

Expand Down Expand Up @@ -115,9 +115,9 @@
expect {
AggregateDataQuery.new(
group_by_fields: [
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("iso_country_code"),
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("address.iso_region_code"),
V1::BeneficiaryStatsRequestSchema::FIELDS.fetch("address.administrative_division_level_2_code")
BeneficiaryField.find("iso_country_code"),
BeneficiaryField.find("address.iso_region_code"),
BeneficiaryField.find("address.administrative_division_level_2_code")
],
).apply(Contact.all)
}.to raise_error(AggregateDataQuery::TooManyResultsError)
Expand Down
10 changes: 5 additions & 5 deletions spec/request_schemas/v1/beneficiary_stats_request_schema_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ module V1
).output

expect(result[:filter_fields]).to include(
BeneficiaryStatsRequestSchema::FIELDS.fetch("gender") => "M",
BeneficiaryStatsRequestSchema::FIELDS.fetch("iso_country_code") => "KH"
BeneficiaryField.find("gender") => "M",
BeneficiaryField.find("iso_country_code") => "KH"
)
expect(result[:group_by_fields]).to contain_exactly(
BeneficiaryStatsRequestSchema::FIELDS.fetch("iso_country_code"),
BeneficiaryStatsRequestSchema::FIELDS.fetch("gender"),
BeneficiaryStatsRequestSchema::FIELDS.fetch("address.iso_region_code")
BeneficiaryField.find("iso_country_code"),
BeneficiaryField.find("gender"),
BeneficiaryField.find("address.iso_region_code")
)
end

Expand Down

0 comments on commit 454566f

Please sign in to comment.