diff --git a/dashboard/app/models/user_level.rb b/dashboard/app/models/user_level.rb index 6779fb6ad7d25..568c232345bed 100644 --- a/dashboard/app/models/user_level.rb +++ b/dashboard/app/models/user_level.rb @@ -36,6 +36,8 @@ class UserLevel < ApplicationRecord after_save :after_submit, if: :submitted_or_resubmitted? before_save :before_unsubmit, if: ->(ul) {ul.submitted_changed? from: true, to: false} + validate :readonly_requires_submitted + # TODO(asher): Consider making these scopes and the methods below more consistent, in tense and in # word choice. scope :attempted, -> {where.not(best_result: nil)} @@ -47,6 +49,12 @@ def self.by_stage(stage) where(script: stage.script, level: levels) end + def readonly_requires_submitted + if readonly_answers? && !submitted? + errors.add(:readonly_answers, 'readonly_answers only valid on submitted UserLevel') + end + end + def attempted? !best_result.nil? end @@ -159,6 +167,7 @@ def self.update_lockable_state(user_id, level_id, script_id, locked, readonly_an return if !user_level.persisted? && locked user_level.assign_attributes( + submitted: locked || readonly_answers, readonly_answers: !locked && readonly_answers, unlocked_at: locked ? nil : Time.now, # level_group, which is the only levels that we lock, always sets best_result to 100 when complete diff --git a/dashboard/test/controllers/api_controller_test.rb b/dashboard/test/controllers/api_controller_test.rb index a1e6f61c88d81..7f1389d1382aa 100644 --- a/dashboard/test/controllers/api_controller_test.rb +++ b/dashboard/test/controllers/api_controller_test.rb @@ -383,7 +383,7 @@ class ApiControllerTest < ActionController::TestCase post :update_lockable_state, params: {updates: updates} user_level = UserLevel.find_by(user_level_data) - assert_equal false, user_level.submitted? + assert_equal true, user_level.submitted? assert_equal true, user_level.readonly_answers? assert_not_nil user_level.unlocked_at @@ -436,7 +436,7 @@ class ApiControllerTest < ActionController::TestCase post :update_lockable_state, params: {updates: updates} user_level = UserLevel.find_by(user_level_data) - assert_equal false, user_level.submitted? + assert_equal true, user_level.submitted? assert_equal false, user_level.readonly_answers? assert_nil user_level.unlocked_at # update_lockable_state does not modify updated_at @@ -456,7 +456,7 @@ class ApiControllerTest < ActionController::TestCase post :update_lockable_state, params: {updates: updates} user_level = UserLevel.find_by(user_level_data) - assert_equal false, user_level.submitted? + assert_equal true, user_level.submitted? assert_equal true, user_level.readonly_answers? assert_not_nil user_level.unlocked_at assert_equal expected_updated_at, user_level.updated_at @@ -494,7 +494,7 @@ class ApiControllerTest < ActionController::TestCase post :update_lockable_state, params: {updates: updates} user_level = UserLevel.find_by(user_level_data) - assert_equal true, user_level.submitted? + assert_equal false, user_level.submitted? assert_equal false, user_level.readonly_answers? assert_not_nil user_level.unlocked_at assert_equal expected_updated_at, user_level.updated_at