Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add data migration to associate modern language child subjects #673

Merged
merged 1 commit into from
May 23, 2024
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
48 changes: 34 additions & 14 deletions app/services/publish_teacher_training/subject/import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ module Subject
class Import
include ServicePattern

PRIMARY_IDS = %w[PrimarySubject].freeze
SECONDARY_IDS = %w[SecondarySubject ModernLanguagesSubject].freeze
PRIMARY_ID = "PrimarySubject".freeze
SECONDARY_ID = "SecondarySubject".freeze
MODERN_LANGUAGES_ID = "ModernLanguagesSubject".freeze

def call
fetch_subject
Expand All @@ -15,9 +16,12 @@ def call
def fetch_subject
api_response = PublishTeacherTraining::Subject::Api.call
data = api_response.fetch("data")
# Find Primary Subjects IDs
primary_subject_ids = fetch_subject_ids(subject_area_ids: PRIMARY_IDS, data:)
secondary_subject_ids = fetch_subject_ids(subject_area_ids: SECONDARY_IDS, data:)
# Find Primary Subject IDs
primary_subject_ids = fetch_subject_ids(subject_area_id: PRIMARY_ID, data:)
# Find Secondary Subject IDs
secondary_subject_ids = fetch_subject_ids(subject_area_id: SECONDARY_ID, data:)
# Find Modern Language Subject IDs
modern_language_subject_ids = fetch_subject_ids(subject_area_id: MODERN_LANGUAGES_ID, data:)

subjects_data = api_response.fetch("included")
# Sync Primary Subjects
Expand All @@ -33,36 +37,52 @@ def fetch_subject
subject_ids: secondary_subject_ids,
subjects_data:,
)

# Sync Modern Language Subjects
sync_subjects(
subject_area: :secondary,
subject_ids: modern_language_subject_ids,
subjects_data:,
parent_subject: ::Subject.find_by(name: "Modern Languages"),
ollietreend marked this conversation as resolved.
Show resolved Hide resolved
)
end

def sync_subjects(subject_area:, subject_ids:, subjects_data:)
def sync_subjects(subject_area:, subject_ids:, subjects_data:, parent_subject: nil)
return if subject_ids.blank?

subject_area_subjects_data = subjects_data.select do |subject|
subject_ids.include?(subject["id"])
end
subject_area_subjects_data.each do |subject_data|
subject_attributes = subject_data.fetch("attributes")
begin
::Subject.find_or_create_by!(
subject = ::Subject.find_or_create_by!(
subject_area:,
name: subject_attributes.fetch("name"),
code: subject_attributes.fetch("code"),
)
# Parent subject assigned separately, in case the subject already
# exists without the parent subject associated.
next if parent_subject.blank?

subject.update!(parent_subject:)
rescue ActiveRecord::RecordInvalid => e
Sentry.capture_exception(e)
end
end
end

def fetch_subject_ids(subject_area_ids:, data:)
def fetch_subject_ids(subject_area_id:, data:)
subject_ids = []

subject_areas = data.select do |subject_area_data|
subject_area_ids.include?(subject_area_data.fetch("id"))
subject_area = data.find do |subject_area_data|
subject_area_data["id"] == subject_area_id
end
subject_areas.each do |subject_area|
subject_area.dig("relationships", "subjects", "data").each do |subject_data|
subject_ids << subject_data["id"]
end

return if subject_area.blank?

subject_area.dig("relationships", "subjects", "data").each do |subject_data|
subject_ids << subject_data["id"]
end

subject_ids
Expand Down
55 changes: 55 additions & 0 deletions db/data/20240522123948_update_modern_language_child_subjects.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class UpdateModernLanguageChildSubjects < ActiveRecord::Migration[7.1]
def up
api_response = PublishTeacherTraining::Subject::Api.call
child_subject_ids = modern_language_child_subject_ids(api_response.fetch("data"))

subjects_data = api_response.fetch("included")

assign_parent_subject(parent_subject: modern_languages, child_subject_ids:, subjects_data:)
end

def down
return if modern_languages.blank?

Subject.where(parent_subject: modern_languages).update_all(parent_subject_id: nil)
JamieCleare2525 marked this conversation as resolved.
Show resolved Hide resolved
end

private

def modern_languages
@modern_languages ||= Subject.find_by(name: "Modern Languages")
end

def modern_language_child_subject_ids(data)
subject_ids = []

modern_language_subject_area = data.find do |subject_area|
subject_area["id"] == "ModernLanguagesSubject"
end

modern_language_subject_area.dig("relationships", "subjects", "data").each do |subject_data|
subject_ids << subject_data["id"]
end

subject_ids
end

def assign_parent_subject(parent_subject:, child_subject_ids:, subjects_data:)
return if parent_subject.blank?

child_subjects_data = subjects_data.select do |subject|
child_subject_ids.include?(subject["id"])
end

child_subjects_data.each do |child_subject_data|
subject_attributes = child_subject_data["attributes"]
child_subject = Subject.find_by(
name: subject_attributes["name"],
code: subject_attributes["code"],
)
next if child_subject.blank?

child_subject.update!(parent_subject:)
end
end
end
1 change: 1 addition & 0 deletions db/data_schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DataMigrate::Data.define(version: 20240522123948)
23 changes: 20 additions & 3 deletions spec/services/publish_teacher_training/subject/import_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,20 @@
described_class.call
}.to change(Subject.primary, :count).by(2).and change(
Subject.secondary, :count
).by(3)
).by(4)

expect(Subject.primary.pluck(:name)).to match_array([
"Primary", "Primary with English"
])

expect(Subject.secondary.pluck(:name)).to match_array([
"Art and design", "Science", "French"
"Art and design", "Science", "French", "Modern Languages"
])

modern_languages = Subject.find_by(name: "Modern Languages")
expect(modern_languages.child_subjects.pluck(:name)).to match_array(
%w[French],
)
end

context "when a subject already exists" do
Expand All @@ -33,7 +38,7 @@

expect {
described_class.call
}.to change(Subject, :count).by(4)
}.to change(Subject, :count).by(5)
end
end
end
Expand Down Expand Up @@ -147,6 +152,10 @@ def response_body
"type" => "subjects",
"id" => "4",
},
{
"type" => "subjects",
"id" => "7",
},
],
},
},
Expand Down Expand Up @@ -209,6 +218,14 @@ def response_body
"code" => "F0",
},
},
{
"id" => "7",
"type" => "subjects",
"attributes" => {
"name" => "Modern Languages",
"code" => nil,
},
},
{
"id" => "5",
"attributes" => {
Expand Down