Skip to content

Commit 9216d3f

Browse files
authored
Pass remix identifier through with lesson list (#608)
## Status - Related to RaspberryPiFoundation/digital-editor-issues#994 ## What's changed? - Requests to list lessons now include a remix identifier if the user has one - Added route to show the identifier of a remix of a given project
1 parent f8689ca commit 9216d3f

File tree

6 files changed

+79
-4
lines changed

6 files changed

+79
-4
lines changed

app/controllers/api/lessons_controller.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ def index
1010
archive_scope = params[:include_archived] == 'true' ? Lesson : Lesson.unarchived
1111
scope = params[:school_class_id] ? archive_scope.where(school_class_id: params[:school_class_id]) : archive_scope
1212
ordered_scope = scope.order(created_at: :asc)
13-
@lessons_with_users = ordered_scope.accessible_by(current_ability).with_users
13+
accessible_lessons = ordered_scope.accessible_by(current_ability)
14+
lessons_with_users = accessible_lessons.with_users
15+
remixes = user_remixes(accessible_lessons)
16+
@lessons_with_users_and_remixes = lessons_with_users.zip(remixes)
1417
render :index, formats: [:json], status: :ok
1518
end
1619

@@ -74,6 +77,22 @@ def verify_school_class_belongs_to_school
7477
raise ParameterError, 'school_class_id does not correspond to school_id'
7578
end
7679

80+
def user_remixes(lessons)
81+
lessons.map do |lesson|
82+
next nil unless lesson&.project&.remixes&.any?
83+
84+
user_remix(lesson)
85+
end
86+
end
87+
88+
def user_remix(lesson)
89+
lesson.project&.remixes
90+
&.where(user_id: current_user.id)
91+
&.accessible_by(current_ability)
92+
&.order(created_at: :asc)
93+
&.first
94+
end
95+
7796
def lesson_params
7897
base_params.merge(user_id: current_user.id)
7998
end

app/controllers/api/projects/remixes_controller.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Projects
55
class RemixesController < ApiController
66
before_action :authorize_user
77
load_and_authorize_resource :school, only: :index
8-
before_action :load_and_authorize_remix, only: %i[show]
8+
before_action :load_and_authorize_remix, only: %i[show show_identifier]
99

1010
def index
1111
projects = Project.where(remixed_from_id: project.id).accessible_by(current_ability)
@@ -17,6 +17,10 @@ def show
1717
render '/api/projects/show', formats: [:json]
1818
end
1919

20+
def show_identifier
21+
render json: { identifier: @project.identifier }, status: :ok
22+
end
23+
2024
def create
2125
# Ensure we have a fallback value to prevent bad requests
2226
remix_origin = request.origin || request.referer

app/views/api/lessons/index.json.jbuilder

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

3-
json.array!(@lessons_with_users) do |lesson, user|
3+
json.array!(@lessons_with_users_and_remixes) do |lesson_with_user, remix|
4+
lesson, user = lesson_with_user # Destructure the pair
45
json.call(
56
lesson,
67
:id,
@@ -26,4 +27,6 @@ json.array!(@lessons_with_users) do |lesson, user|
2627
end
2728

2829
json.user_name(user&.name)
30+
31+
json.remix_identifier(remix.identifier) if remix.present?
2932
end

config/routes.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@
4343
post :submit, on: :member, to: 'school_projects#submit'
4444
post :return, on: :member, to: 'school_projects#return'
4545
post :complete, on: :member, to: 'school_projects#complete'
46-
resource :remix, only: %i[show create], controller: 'projects/remixes'
46+
resource :remix, only: %i[show create], controller: 'projects/remixes' do
47+
get :identifier, on: :member, to: 'projects/remixes#show_identifier'
48+
end
4749
resources :remixes, only: %i[index], controller: 'projects/remixes'
4850
resource :images, only: %i[show create], controller: 'projects/images'
4951
resources :feedback, only: %i[index create], controller: 'feedback' do

spec/features/lesson/listing_lessons_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,17 @@
210210
expect(data.size).to eq(1)
211211
end
212212

213+
it "includes the remix identifier when the user has remixed the lesson's project" do
214+
student = create(:student, school:)
215+
authenticated_in_hydra_as(student)
216+
create(:class_student, school_class:, student_id: student.id)
217+
student_project = create(:project, school:, lesson:, parent: lesson.project, user_id: student.id)
218+
219+
get('/api/lessons', headers:)
220+
data = JSON.parse(response.body, symbolize_names: true)
221+
expect(data.first[:remix_identifier]).to eq(student_project.identifier)
222+
end
223+
213224
it "does not include the lesson when the user is not a school-student within the lesson's class" do
214225
student = create(:student, school:)
215226
authenticated_in_hydra_as(student)

spec/requests/projects/remix_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,35 @@
7070
end
7171
end
7272

73+
describe('#show_identifier') do
74+
let!(:remixed_project) do
75+
create(:project, remixed_from_id: original_project.id, user_id: authenticated_user.id)
76+
end
77+
78+
it 'returns success response' do
79+
get("/api/projects/#{original_project.identifier}/remix/identifier", headers:)
80+
expect(response).to have_http_status(:ok)
81+
end
82+
83+
it 'returns the project identifier' do
84+
get("/api/projects/#{original_project.identifier}/remix/identifier", headers:)
85+
expect(response.parsed_body['identifier']).to eq(remixed_project.identifier)
86+
end
87+
88+
it 'returns 404 response if invalid project' do
89+
get('/api/projects/no-such-project/remix/identifier', headers:)
90+
expect(response).to have_http_status(:not_found)
91+
end
92+
93+
it 'returns 404 if no remixed project for user' do
94+
another_user = create(:owner, school:)
95+
authenticated_in_hydra_as(another_user)
96+
97+
get("/api/projects/#{original_project.identifier}/remix/identifier", headers:)
98+
expect(response).to have_http_status(:not_found)
99+
end
100+
end
101+
73102
describe '#create' do
74103
it 'returns success response' do
75104
post("/api/projects/#{original_project.identifier}/remix", params: { project: project_params }, headers:)
@@ -116,6 +145,13 @@
116145
end
117146
end
118147

148+
describe '#show_identifier' do
149+
it 'returns unauthorized' do
150+
get "/api/projects/#{original_project.identifier}/remix/identifier"
151+
expect(response).to have_http_status(:unauthorized)
152+
end
153+
end
154+
119155
describe '#create' do
120156
it 'returns unauthorized' do
121157
post "/api/projects/#{original_project.identifier}/remix"

0 commit comments

Comments
 (0)