Skip to content

Commit 7183dc7

Browse files
loiswells97jamiebensteadchrisroosdanhalson
authored
Add school_project model and refactor routes to get and set the finished flag (#490)
## Status closes #485 --------- Co-authored-by: Jamie Benstead <[email protected]> Co-authored-by: Chris Roos <[email protected]> Co-authored-by: Dan Halson <[email protected]>
1 parent b45c660 commit 7183dc7

25 files changed

+300
-79
lines changed

app/controllers/api/projects/remixes_controller.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class RemixesController < ApiController
88

99
def index
1010
projects = Project.where(remixed_from_id: project.id).accessible_by(current_ability)
11-
@projects_with_users = projects.with_users(@current_user)
11+
@projects_with_users = projects.includes(:school_project).with_users(@current_user)
1212
render index: @projects_with_users, formats: [:json]
1313
end
1414

@@ -47,6 +47,9 @@ def remix_params
4747
:project_type,
4848
:locale,
4949
:user_id,
50+
:videos,
51+
:audio,
52+
:instructions,
5053
image_list: [],
5154
components: %i[id name extension content index])
5255
end

app/controllers/api/projects_controller.rb

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
module Api
66
class ProjectsController < ApiController
77
before_action :authorize_user, only: %i[create update index destroy]
8-
before_action :load_project, only: %i[show update toggle_finished destroy]
8+
before_action :load_project, only: %i[show update destroy]
99
before_action :load_projects, only: %i[index]
1010
load_and_authorize_resource
1111
before_action :verify_lesson_belongs_to_school, only: :create
@@ -36,16 +36,6 @@ def create
3636
end
3737
end
3838

39-
def toggle_finished
40-
result = Project::ToggleFinished.call(project: @project)
41-
42-
if result.success?
43-
head :ok
44-
else
45-
render json: { error: result[:error] }, status: :unprocessable_entity
46-
end
47-
end
48-
4939
def update
5040
result = Project::Update.call(project: @project, update_hash: project_params, current_user: @current_user)
5141

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# frozen_string_literal: true
2+
3+
module Api
4+
class SchoolProjectsController < ApiController
5+
before_action :authorize_user
6+
load_and_authorize_resource :project
7+
8+
def show_finished
9+
@school_project = Project.find_by(identifier: params[:id]).school_project
10+
render :finished, formats: [:json], status: :ok
11+
end
12+
13+
def set_finished
14+
project = Project.find_by(identifier: params[:id])
15+
result = SchoolProject::SetFinished.call(school_project: project.school_project, finished: params[:finished])
16+
17+
if result.success?
18+
@school_project = result[:school_project]
19+
render :finished, formats: [:json], status: :ok
20+
else
21+
render json: { error: result[:error] }, status: :unprocessable_entity
22+
end
23+
end
24+
end
25+
end

app/models/ability.rb

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ def initialize(user)
99
return unless user
1010

1111
define_authenticated_non_student_abilities(user)
12-
1312
user.schools.each do |school|
1413
define_school_student_abilities(user:, school:) if user.school_student?(school)
1514
define_school_teacher_abilities(user:, school:) if user.school_teacher?(school)
@@ -99,16 +98,7 @@ def define_school_student_abilities(user:, school:)
9998
can(%i[read], Lesson, school_id: school.id, visibility: 'students', school_class: { members: { student_id: user.id } })
10099
can(%i[read create update], Project, school_id: school.id, user_id: user.id, lesson_id: nil)
101100
can(%i[read], Project, lesson: { school_id: school.id, school_class: { members: { student_id: user.id } } })
102-
can(%i[toggle_finished], Project) do |project|
103-
school_student_can_toggle_finished?(user:, school:, project:)
104-
end
105-
end
106-
107-
def school_student_can_toggle_finished?(user:, school:, project:)
108-
is_my_project = project.user_id == user.id && project.school_id == school.id
109-
is_a_remix = project.remixed_from_id.present?
110-
111-
is_my_project && is_a_remix
101+
can(%i[show_finished set_finished], SchoolProject, project: { user_id: user.id, lesson_id: nil }, school_id: school.id)
112102
end
113103

114104
def school_teacher_can_manage_lesson?(user:, school:, lesson:)

app/models/project.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,21 @@ class Project < ApplicationRecord
1010
has_many_attached :images
1111
has_many_attached :videos
1212
has_many_attached :audio
13+
has_one :school_project, dependent: :destroy
1314

1415
accepts_nested_attributes_for :components
1516

1617
before_validation :check_unique_not_null, on: :create
18+
before_validation :create_school_project_if_needed
1719

1820
validates :identifier, presence: true, uniqueness: { scope: :locale }
1921
validate :identifier_cannot_be_taken_by_another_user
2022
validates :locale, presence: true, unless: :user_id
2123
validate :user_has_a_role_within_the_school
2224
validate :user_is_a_member_or_the_owner_of_the_lesson
2325
validate :project_with_instructions_must_belong_to_school
26+
validate :project_with_school_id_has_school_project
27+
validate :school_project_school_matches_project_school
2428

2529
scope :internal_projects, -> { where(user_id: nil) }
2630

@@ -70,6 +74,12 @@ def check_unique_not_null
7074
self.identifier ||= PhraseIdentifier.generate
7175
end
7276

77+
def create_school_project_if_needed
78+
return unless school.present? && school_project.nil?
79+
80+
self.school_project = SchoolProject.new(school:)
81+
end
82+
7383
def identifier_cannot_be_taken_by_another_user
7484
return if Project.where(identifier: self.identifier).where.not(user_id:).empty?
7585

@@ -98,4 +108,16 @@ def project_with_instructions_must_belong_to_school
98108

99109
errors.add(:instructions, 'Projects with instructions must belong to a school')
100110
end
111+
112+
def project_with_school_id_has_school_project
113+
return unless school_id && !school_project
114+
115+
errors.add(:school_project, 'Project with school_id must have a school_project')
116+
end
117+
118+
def school_project_school_matches_project_school
119+
return unless school_id && school_project && school_id != school_project.school_id
120+
121+
errors.add(:school_project, 'School project school_id must match project school_id')
122+
end
101123
end

app/models/school.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ class School < ApplicationRecord
55
has_many :lessons, dependent: :nullify
66
has_many :projects, dependent: :nullify
77
has_many :roles, dependent: :nullify
8+
has_many :school_projects, dependent: :nullify
89

910
VALID_URL_REGEX = %r{\A(?:https?://)?(?:www.)?[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,63}(\.[a-z]{2,63})*(/.*)?\z}ix
1011

app/models/school_project.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# frozen_string_literal: true
2+
3+
class SchoolProject < ApplicationRecord
4+
belongs_to :school
5+
belongs_to :project
6+
end

app/views/api/projects/remixes/index.json.jbuilder

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ json.array!(@projects_with_users) do |project, user|
1212
)
1313

1414
json.user_name(user&.name)
15+
json.finished(project.school_project&.finished)
1516
end

app/views/api/projects/show.json.jbuilder

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,3 @@ json.audio(@project.audio) do |audio_file|
4242
end
4343

4444
json.user_name(@user&.name) if @user.present? && @project.parent
45-
46-
json.finished(@project.finished) if @project.school.present? && @project.remixed_from_id.present?
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
json.call(
4+
@school_project,
5+
:id,
6+
:school_id,
7+
:project_id,
8+
:finished
9+
)
10+
11+
json.identifier(@school_project.project.identifier)

0 commit comments

Comments
 (0)