Skip to content

Commit 700b074

Browse files
authored
Merge branch 'main' into 1130_store-and-return-scratch-data
2 parents 3463ed5 + 726c3fa commit 700b074

8 files changed

Lines changed: 119 additions & 36 deletions

File tree

.clabot

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"contributors": [
3+
"abcampo-iry",
34
"adrian-rpf",
45
"ce-rpf",
56
"chris.lowis@gofreerange.com",
@@ -12,6 +13,7 @@
1213
"cursoragent",
1314
"danhalson",
1415
"dependabot[bot]",
16+
"DNR500",
1517
"fspeirs",
1618
"grega",
1719
"IzzySmillie",

app/controllers/api/lessons_controller.rb

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module Api
44
class LessonsController < ApiController
5+
include RemixSelection
6+
57
before_action :authorize_user, except: %i[index show]
68
before_action :verify_school_class_belongs_to_school, only: :create
79
load_and_authorize_resource :lesson
@@ -82,24 +84,17 @@ def verify_school_class_belongs_to_school
8284
end
8385

8486
def user_remixes(lessons)
85-
lessons.map do |lesson|
86-
next nil unless lesson&.project&.remixes&.any?
87-
88-
user_remix(lesson)
89-
end
87+
lessons.map { |lesson| user_remix(lesson) }
9088
end
9189

9290
def user_remix(lesson)
93-
remixes = lesson&.project&.remixes
91+
return nil unless lesson&.project&.remixes&.any?
9492

95-
remixes = remixes
96-
.where(user_id: current_user.id)
97-
.accessible_by(current_ability)
98-
.order(created_at: :asc)
99-
100-
remixes = remixes.includes(school_project: :feedback) if current_user&.school_student?(school)
101-
102-
remixes.first
93+
remix_for_user(
94+
lesson.project,
95+
current_user,
96+
include_feedback: current_user&.school_student?(school)
97+
)
10398
end
10499

105100
def lesson_params

app/controllers/api/projects/remixes_controller.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
module Api
44
module Projects
55
class RemixesController < ApiController
6+
include RemixSelection
7+
68
before_action :authorize_user
79
load_and_authorize_resource :school, only: :index
810
before_action :load_and_authorize_remix, only: %i[show show_identifier]
@@ -44,7 +46,9 @@ def project
4446
end
4547

4648
def load_and_authorize_remix
47-
@project = Project.find_by!(remixed_from_id: project.id, user_id: current_user&.id)
49+
@project = remix_for_user(project, current_user)
50+
raise ActiveRecord::RecordNotFound unless @project
51+
4852
authorize! :show, @project
4953
end
5054

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
module RemixSelection
4+
extend ActiveSupport::Concern
5+
6+
def remix_for_user(project, user, include_feedback: false)
7+
return nil if user.nil?
8+
9+
query = Project.where(remixed_from_id: project.id, user_id: user.id)
10+
.order(created_at: :asc)
11+
.accessible_by(current_ability)
12+
13+
query = query.includes(school_project: :feedback) if include_feedback
14+
15+
query.first
16+
end
17+
end

lib/tasks/seeds_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def create_school(creator_id, school_id = nil)
3232
# Country-specific required fields
3333
school.reference = format('%06d', rand(100_000..999_999)) if country_code == 'GB'
3434
if country_code == 'US'
35-
school.district_nces_id = format('%012d', rand(10**12))
35+
school.district_nces_id = format('%07d', rand(10**7))
3636
school.district_name = Faker::Address.community
3737
end
3838
school.school_roll_number = "#{rand(10_000..99_999)}#{('A'..'Z').to_a.sample}" if country_code == 'IE'

lib/tasks/test_seeds.rake

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,32 +44,31 @@ namespace :test_seeds do
4444

4545
desc 'Create a school with lessons and students'
4646
task create: :environment do
47-
if School.find_by(code: TEST_SCHOOL)
47+
if School.exists?(id: TEST_SCHOOL)
4848
puts "Test school (#{TEST_SCHOOL}) already exists, run the destroy_seed_data task to start over)."
49-
return
50-
end
51-
52-
ActiveRecord::Base.transaction do
53-
Rails.logger.info 'Attempting to seed data...'
54-
creator_id = ENV.fetch('SEEDING_CREATOR_ID', TEST_USERS[:jane_doe])
55-
teacher_id = ENV.fetch('SEEDING_TEACHER_ID', TEST_USERS[:john_doe])
49+
else
50+
ActiveRecord::Base.transaction do
51+
Rails.logger.info 'Attempting to seed data...'
52+
creator_id = ENV.fetch('SEEDING_CREATOR_ID', TEST_USERS[:jane_doe])
53+
teacher_id = ENV.fetch('SEEDING_TEACHER_ID', TEST_USERS[:john_doe])
5654

57-
school = create_school(creator_id, TEST_SCHOOL)
58-
verify_school(school)
59-
assign_a_teacher(teacher_id, school)
55+
school = create_school(creator_id, TEST_SCHOOL)
56+
verify_school(school)
57+
assign_a_teacher(teacher_id, school)
6058

61-
# for each of the owner and teacher, create a class and assign students
62-
[creator_id, teacher_id].each do |user_id|
63-
teacher_name = user_id == creator_id ? 'Jane Doe' : 'John Doe'
64-
school_class = create_school_class(user_id, school, "#{teacher_name}'s Class", "A class for #{teacher_name}'s students")
65-
assign_students(school_class, school)
59+
# for each of the owner and teacher, create a class and assign students
60+
[creator_id, teacher_id].each do |user_id|
61+
teacher_name = user_id == creator_id ? 'Jane Doe' : 'John Doe'
62+
school_class = create_school_class(user_id, school, "#{teacher_name}'s Class", "A class for #{teacher_name}'s students")
63+
assign_students(school_class, school)
6664

67-
lessons = create_lessons(user_id, school, school_class)
68-
lessons.each do |lesson|
69-
create_project(user_id, school, lesson, 'print("Hello World!")')
65+
lessons = create_lessons(user_id, school, school_class)
66+
lessons.each do |lesson|
67+
create_project(user_id, school, lesson, 'print("Hello World!")')
68+
end
7069
end
70+
Rails.logger.info 'Done...'
7171
end
72-
Rails.logger.info 'Done...'
7372
end
7473
end
7574
end

spec/lib/test_seeds_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@
3636

3737
describe ':seed_a_school_with_lessons_and_students' do
3838
let(:task) { Rake::Task['test_seeds:create'] }
39+
let(:seed_country_code) { nil }
3940

4041
before do
42+
allow(Faker::Address).to receive(:country_code).and_return(seed_country_code) if seed_country_code
4143
task.reenable
4244
task.invoke
4345
end
@@ -82,6 +84,20 @@
8284
expect(ClassTeacher.where(teacher_id:).length).to eq(1)
8385
end
8486

87+
it 'is idempotent' do
88+
school = School.find_by!(creator_id:)
89+
owner_class = SchoolClass.joins(:teachers).find_by!(school_id: school.id, teachers: { teacher_id: creator_id })
90+
teacher_class = SchoolClass.joins(:teachers).find_by!(school_id: school.id, teachers: { teacher_id: })
91+
92+
expect do
93+
task.reenable
94+
task.invoke
95+
end.not_to change { [SchoolClass.where(school_id: school.id).count, Lesson.where(school_id: school.id).count, Project.where(school_id: school.id).count] }
96+
97+
expect(owner_class.reload.lessons.count).to eq(2)
98+
expect(teacher_class.reload.lessons.count).to eq(2)
99+
end
100+
85101
it 'assigns students' do
86102
school_id = School.find_by(creator_id:).id
87103
school_class_id = SchoolClass.find_by(school_id:).id
@@ -90,5 +106,20 @@
90106
expect(Role.student.where(user_id: student_2, school_id:)).to exist
91107
expect(ClassStudent.where(student_id: student_2, school_class_id:)).to exist
92108
end
109+
110+
context 'when the seeded school is in the US' do
111+
let(:seed_country_code) { 'US' }
112+
113+
it 'creates a valid school and owner lessons' do
114+
school = School.find_by(creator_id:)
115+
school_class = SchoolClass.joins(:teachers).find_by(school_id: school.id, teachers: { teacher_id: creator_id })
116+
117+
expect(school).to be_valid
118+
expect(school.district_nces_id).to match(/\A\d{7}\z/)
119+
expect(school.district_name).to be_present
120+
expect(school_class).not_to be_nil
121+
expect(Lesson.where(school_id: school.id, school_class_id: school_class.id).length).to eq(2)
122+
end
123+
end
93124
end
94125
end

spec/requests/projects/remix_spec.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,24 @@
7171

7272
expect(response).to have_http_status(:not_found)
7373
end
74+
75+
context 'when multiple remixes exist for the same user and project' do
76+
let!(:oldest_remix) do
77+
create(:project, remixed_from_id: original_project.id, user_id: authenticated_user.id,
78+
created_at: 2.days.ago, updated_at: 2.days.ago)
79+
end
80+
81+
before do
82+
create(:project, remixed_from_id: original_project.id, user_id: authenticated_user.id,
83+
created_at: 1.hour.from_now, updated_at: 1.hour.from_now)
84+
end
85+
86+
it 'returns the oldest created remix' do
87+
get("/api/projects/#{original_project.identifier}/remix", headers:)
88+
89+
expect(response.parsed_body['identifier']).to eq(oldest_remix.identifier)
90+
end
91+
end
7492
end
7593

7694
describe('#show_identifier') do
@@ -100,6 +118,23 @@
100118
get("/api/projects/#{original_project.identifier}/remix/identifier", headers:)
101119
expect(response).to have_http_status(:not_found)
102120
end
121+
122+
context 'when multiple remixes exist for the same user and project' do
123+
let!(:oldest_remix) do
124+
create(:project, remixed_from_id: original_project.id, user_id: authenticated_user.id,
125+
created_at: 2.days.ago, updated_at: 2.days.ago)
126+
end
127+
128+
before do
129+
create(:project, remixed_from_id: original_project.id, user_id: authenticated_user.id,
130+
created_at: 1.hour.from_now, updated_at: 1.hour.from_now)
131+
end
132+
133+
it 'returns the identifier of the oldest created remix' do
134+
get("/api/projects/#{original_project.identifier}/remix/identifier", headers:)
135+
expect(response.parsed_body['identifier']).to eq(oldest_remix.identifier)
136+
end
137+
end
103138
end
104139

105140
describe '#create' do

0 commit comments

Comments
 (0)