# frozen_string_literal: true class LinterCheckRun < ApplicationRecord belongs_to :linter_check belongs_to :testrun belongs_to :file, class_name: 'CodeOcean::File' def self.create_from(testrun, assessment) linter_check_runs = create_linter_check_runs(testrun, assessment) validate_and_store!(linter_check_runs) end def self.create_linter_check_runs(testrun, assessment) assessment[:detailed_linter_results]&.map do |linter_result| check = LinterCheck.find_or_create_by!(code: linter_result[:code]) do |new_check| new_check.name = linter_result[:name] new_check.severity = linter_result[:severity] end file = testrun.submission.file_by_name(linter_result[:file_name]) LinterCheckRun.new( linter_check: check, result: linter_result[:result], line: linter_result[:line], scope: linter_result[:scope], testrun:, file: ) end end private_class_method :create_linter_check_runs def self.validate_and_store!(linter_check_runs) validated_check_runs = linter_check_runs.map do |check_run| check_run.validate! # We serialize the message without the ID, created_at and updated_at, as they are generated by the database. check_run.serializable_hash(except: %w[id created_at updated_at]) rescue ActiveRecord::RecordInvalid # Something bad happened. Probably, the RegEx in lib/py_lint_adapter.rb didn't work. Sentry.set_extras(testrun: testrun.inspect, linter_result:) end # Now, we store all check runs and skip validations (they are already done) LinterCheckRun.insert_all!(validated_check_runs) if validated_check_runs.present? # rubocop:disable Rails/SkipsModelValidations end private_class_method :validate_and_store! end