rubocop: Rails/InverseOf

[skip-crystalball]

Enabled config.active_record.automatic_scope_inversing so that Rails will
auto-infer lots more of them, and then go through the remaining offenses
(mostly once with foreign_key specified)

Change-Id: Ida8c67c9492a357a148b6d97356a6d4b20523ce8
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/358318
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Jacob Burroughs <jburroughs@instructure.com>
QA-Review: Cody Cutrer <cody@instructure.com>
Product-Review: Cody Cutrer <cody@instructure.com>
This commit is contained in:
Cody Cutrer 2024-09-24 10:33:16 -06:00
parent 8da90ee5a4
commit d13763d789
31 changed files with 121 additions and 110 deletions

View File

@ -127,6 +127,8 @@ Rails/I18nLocaleTexts:
Exclude:
- spec/**/*.rb
- "**/spec_canvas/**/*.rb"
Rails/InverseOf:
IgnoreScopes: true # config.active_record.automatic_scope_inversing is enabled
Rails/NegateInclude:
Enabled: false # exclude? isn't as intuitive as !include?
Rails/Output:
@ -284,8 +286,6 @@ Rails/EagerEvaluationLogMessage:
Rails/FindEach:
Severity: convention
AutoCorrect: false
Rails/InverseOf:
Severity: convention
Rails/LexicallyScopedActionFilter:
Severity: convention
Rails/OutputSafety:

View File

@ -113,7 +113,7 @@ class AbstractAssignment < ActiveRecord::Base
has_many :learning_outcome_alignments, -> { where("content_tags.tag_type='learning_outcome' AND content_tags.workflow_state<>'deleted'").preload(:learning_outcome) }, as: :content, inverse_of: :content, class_name: "ContentTag"
has_one :rubric_association, -> { where(purpose: "grading").order(:created_at).preload(:rubric) }, as: :association, inverse_of: :association_object
has_one :rubric, -> { merge(RubricAssociation.active) }, through: :rubric_association
has_one :teacher_enrollment, -> { preload(:user).where(enrollments: { workflow_state: "active", type: "TeacherEnrollment" }) }, class_name: "TeacherEnrollment", foreign_key: "course_id", primary_key: "context_id"
has_one :teacher_enrollment, -> { preload(:user).where(enrollments: { workflow_state: "active", type: "TeacherEnrollment" }) }, class_name: "TeacherEnrollment", foreign_key: "course_id", primary_key: "context_id", inverse_of: false
has_many :ignores, as: :asset
has_many :moderated_grading_selections, class_name: "ModeratedGrading::Selection", inverse_of: :assignment, foreign_key: :assignment_id
belongs_to :context, polymorphic: [:course]

View File

@ -39,7 +39,7 @@ class Account < ActiveRecord::Base
has_many :custom_grade_statuses, inverse_of: :root_account, foreign_key: :root_account_id
has_many :standard_grade_statuses, inverse_of: :root_account, foreign_key: :root_account_id
has_many :favorites, inverse_of: :root_account
has_many :all_courses, class_name: "Course", foreign_key: "root_account_id"
has_many :all_courses, class_name: "Course", foreign_key: "root_account_id", inverse_of: :root_account
has_one :terms_of_service, dependent: :destroy
has_one :terms_of_service_content, dependent: :destroy
has_many :group_categories, -> { where(deleted_at: nil) }, as: :context, inverse_of: :context
@ -47,21 +47,21 @@ class Account < ActiveRecord::Base
has_many :groups, as: :context, inverse_of: :context
has_many :all_groups, class_name: "Group", foreign_key: "root_account_id", inverse_of: :root_account
has_many :all_group_memberships, source: "group_memberships", through: :all_groups
has_many :enrollment_terms, foreign_key: "root_account_id"
has_many :active_enrollment_terms, -> { where("enrollment_terms.workflow_state<>'deleted'") }, class_name: "EnrollmentTerm", foreign_key: "root_account_id"
has_many :enrollment_terms, foreign_key: "root_account_id", inverse_of: :root_account
has_many :active_enrollment_terms, -> { where("enrollment_terms.workflow_state<>'deleted'") }, class_name: "EnrollmentTerm", foreign_key: "root_account_id", inverse_of: false
has_many :grading_period_groups, inverse_of: :root_account, dependent: :destroy
has_many :grading_periods, through: :grading_period_groups
has_many :enrollments, -> { where("enrollments.type<>'StudentViewEnrollment'") }, foreign_key: "root_account_id"
has_many :all_enrollments, class_name: "Enrollment", foreign_key: "root_account_id"
has_many :enrollments, -> { where("enrollments.type<>'StudentViewEnrollment'") }, foreign_key: "root_account_id", inverse_of: :root_account
has_many :all_enrollments, class_name: "Enrollment", foreign_key: "root_account_id", inverse_of: :root_account
has_many :temporary_enrollment_pairings, inverse_of: :root_account, foreign_key: "root_account_id"
has_many :sub_accounts, -> { where("workflow_state<>'deleted'") }, class_name: "Account", foreign_key: "parent_account_id"
has_many :all_accounts, -> { order(:name) }, class_name: "Account", foreign_key: "root_account_id"
has_many :sub_accounts, -> { where("workflow_state<>'deleted'") }, class_name: "Account", foreign_key: "parent_account_id", inverse_of: :parent_account
has_many :all_accounts, -> { order(:name) }, class_name: "Account", foreign_key: "root_account_id", inverse_of: :root_account
has_many :account_users, dependent: :destroy
has_many :active_account_users, -> { active }, class_name: "AccountUser"
has_many :course_sections, foreign_key: "root_account_id"
has_many :course_sections, foreign_key: "root_account_id", inverse_of: :root_account
has_many :sis_batches
has_many :abstract_courses, class_name: "AbstractCourse"
has_many :root_abstract_courses, class_name: "AbstractCourse", foreign_key: "root_account_id"
has_many :root_abstract_courses, class_name: "AbstractCourse", foreign_key: "root_account_id", inverse_of: :root_account
has_many :user_account_associations
has_many :all_users, -> { distinct }, through: :user_account_associations, source: :user
has_many :users, through: :active_account_users
@ -90,7 +90,7 @@ class Account < ActiveRecord::Base
has_many :assessment_question_banks, -> { preload(:assessment_questions, :assessment_question_bank_users) }, as: :context, inverse_of: :context
has_many :assessment_questions, through: :assessment_question_banks
has_many :roles
has_many :all_roles, class_name: "Role", foreign_key: "root_account_id"
has_many :all_roles, class_name: "Role", foreign_key: "root_account_id", inverse_of: :root_account
has_many :progresses, as: :context, inverse_of: :context
has_many :content_migrations, as: :context, inverse_of: :context
has_many :sis_batch_errors, foreign_key: :root_account_id, inverse_of: :root_account
@ -156,7 +156,7 @@ class Account < ActiveRecord::Base
has_many :report_snapshots
has_many :external_integration_keys, as: :context, inverse_of: :context, dependent: :destroy
has_many :shared_brand_configs
belongs_to :brand_config, foreign_key: "brand_config_md5"
belongs_to :brand_config, foreign_key: "brand_config_md5", inverse_of: :accounts
has_many :blackout_dates, as: :context, inverse_of: :context
before_validation :verify_unique_sis_source_id

View File

@ -22,17 +22,16 @@ class AppointmentGroup < ActiveRecord::Base
include Workflow
include TextHelper
# rubocop:disable Style/RedundantDoubleSplatHashBraces
# see https://github.com/rubocop/rubocop/issues/12263
# rubocop:disable Rails/InverseOf
has_many :appointments,
-> { order(:start_at).preload(:child_events).where("calendar_events.workflow_state <> 'deleted'") },
**(opts = { class_name: "CalendarEvent", as: :context, inverse_of: :context })
# rubocop:enable Style/RedundantDoubleSplatHashBraces
# has_many :through on the same table does not alias columns in condition
# strings, just hashes. we create this helper association to ensure
# appointments_participants conditions have the correct table alias
has_many :_appointments, -> { order(:start_at).preload(:child_events).where("_appointments_appointments_participants.workflow_state <> 'deleted'") }, **opts
# rubocop:enable Rails/InverseOf
has_many :appointments_participants, -> { where("calendar_events.workflow_state <> 'deleted'").order(:start_at) }, through: :_appointments, source: :child_events
has_many :appointment_group_contexts
has_many :appointment_group_sub_contexts, -> { preload(:sub_context) }

View File

@ -117,9 +117,9 @@ class Attachment < ActiveRecord::Base
belongs_to :replacement_attachment, class_name: "Attachment", inverse_of: :replaced_attachments
has_many :replaced_attachments, class_name: "Attachment", foreign_key: "replacement_attachment_id", inverse_of: :replacement_attachment
has_one :sis_batch
has_one :thumbnail, -> { where(thumbnail: "thumb") }, foreign_key: "parent_id"
has_many :thumbnails, foreign_key: "parent_id"
has_many :children, foreign_key: :root_attachment_id, class_name: "Attachment"
has_one :thumbnail, -> { where(thumbnail: "thumb") }, foreign_key: "parent_id", inverse_of: :attachment
has_many :thumbnails, foreign_key: "parent_id", inverse_of: :attachment
has_many :children, foreign_key: :root_attachment_id, class_name: "Attachment", inverse_of: :root_attachment
has_many :attachment_upload_statuses
has_one :crocodoc_document
has_one :canvadoc

View File

@ -38,8 +38,8 @@ class BrandConfig < ActiveRecord::Base
after_save :clear_cache
has_many :accounts, foreign_key: "brand_config_md5"
has_many :shared_brand_configs, foreign_key: "brand_config_md5"
has_many :accounts, foreign_key: "brand_config_md5", inverse_of: :brand_config
has_many :shared_brand_configs, foreign_key: "brand_config_md5", inverse_of: :brand_config
# belongs_to :parent, class_name: "BrandConfig", foreign_key: "parent_md5"
def parent

View File

@ -59,7 +59,7 @@ class ContentTag < ActiveRecord::Base
belongs_to :context_module
belongs_to :learning_outcome
# This allows doing a has_many_through relationship on ContentTags for linked LearningOutcomes. (see LearningOutcomeContext)
belongs_to :learning_outcome_content, class_name: "LearningOutcome", foreign_key: :content_id
belongs_to :learning_outcome_content, class_name: "LearningOutcome", foreign_key: :content_id, inverse_of: false
has_many :learning_outcome_results
belongs_to :root_account, class_name: "Account"

View File

@ -49,10 +49,10 @@ class Course < ActiveRecord::Base
belongs_to :abstract_course
belongs_to :enrollment_term
belongs_to :template_course, class_name: "Course"
has_many :templated_courses, class_name: "Course", foreign_key: "template_course_id"
has_many :templated_accounts, class_name: "Account", foreign_key: "course_template_id"
has_many :templated_courses, class_name: "Course", foreign_key: "template_course_id", inverse_of: :template_course
has_many :templated_accounts, class_name: "Account", foreign_key: "course_template_id", inverse_of: :course_template
belongs_to :linked_homeroom_course, class_name: "Course", foreign_key: "homeroom_course_id"
belongs_to :linked_homeroom_course, class_name: "Course", foreign_key: "homeroom_course_id", inverse_of: false
has_many :course_sections, inverse_of: :course
has_many :active_course_sections, -> { where(workflow_state: "active") }, class_name: "CourseSection", inverse_of: :course
@ -78,7 +78,7 @@ class Course < ActiveRecord::Base
source: :user
has_many :student_enrollments, -> { where("enrollments.workflow_state NOT IN ('rejected', 'completed', 'deleted', 'inactive') AND enrollments.type IN ('StudentEnrollment', 'StudentViewEnrollment')").preload(:user) }, class_name: "Enrollment"
has_many :student_enrollments_including_completed, -> { where("enrollments.workflow_state NOT IN ('rejected', 'deleted', 'inactive') AND enrollments.type IN ('StudentEnrollment', 'StudentViewEnrollment')").preload(:user) }, class_name: "Enrollment", inverse_of: :course
has_many :student_enrollments_including_completed, -> { where("enrollments.workflow_state NOT IN ('rejected', 'deleted', 'inactive') AND enrollments.type IN ('StudentEnrollment', 'StudentViewEnrollment')").preload(:user) }, class_name: "Enrollment"
has_many :students, through: :student_enrollments, source: :user
has_many :self_enrolled_students, -> { where("self_enrolled") }, through: :student_enrollments, source: :user
has_many :admin_visible_student_enrollments, -> { where("enrollments.workflow_state NOT IN ('rejected', 'completed', 'deleted') AND enrollments.type IN ('StudentEnrollment', 'StudentViewEnrollment')").preload(:user) }, class_name: "Enrollment"
@ -220,7 +220,7 @@ class Course < ActiveRecord::Base
has_many :alerts, -> { preload(:criteria) }, as: :context, inverse_of: :context
has_many :appointment_group_contexts, as: :context, inverse_of: :context
has_many :appointment_groups, through: :appointment_group_contexts
has_many :appointment_participants, -> { where("workflow_state = 'locked' AND parent_calendar_event_id IS NOT NULL") }, class_name: "CalendarEvent", foreign_key: :effective_context_code, primary_key: :asset_string
has_many :appointment_participants, -> { where("workflow_state = 'locked' AND parent_calendar_event_id IS NOT NULL") }, class_name: "CalendarEvent", foreign_key: :effective_context_code, primary_key: :asset_string, inverse_of: false
has_many :content_participation_counts, as: :context, inverse_of: :context, dependent: :destroy
has_many :poll_sessions, class_name: "Polling::PollSession", dependent: :destroy
@ -238,7 +238,7 @@ class Course < ActiveRecord::Base
# only valid if non-nil
attr_accessor :is_master_course
has_many :master_course_subscriptions, class_name: "MasterCourses::ChildSubscription", foreign_key: "child_course_id"
has_many :master_course_subscriptions, class_name: "MasterCourses::ChildSubscription", foreign_key: "child_course_id", inverse_of: :child_course
has_one :late_policy, dependent: :destroy, inverse_of: :course
has_many :quiz_migration_alerts, dependent: :destroy
has_many :notification_policy_overrides, as: :context, inverse_of: :context

View File

@ -22,7 +22,7 @@ class CourseAccountAssociation < ActiveRecord::Base
belongs_to :course
belongs_to :course_section
belongs_to :account
has_many :account_users, foreign_key: "account_id", primary_key: "account_id"
has_many :account_users, foreign_key: "account_id", primary_key: "account_id", inverse_of: false
validates :course_id, :account_id, :depth, presence: true

View File

@ -31,17 +31,17 @@ class DiscussionEntry < ActiveRecord::Base
attr_readonly :discussion_topic_id, :user_id, :parent_id, :is_anonymous_author
has_many :discussion_entry_drafts, inverse_of: :discussion_entry
has_many :discussion_entry_versions, -> { order(version: :desc) }, inverse_of: :discussion_entry, dependent: :destroy
has_many :legacy_subentries, class_name: "DiscussionEntry", foreign_key: "parent_id"
has_many :root_discussion_replies, -> { where("parent_id=root_entry_id") }, class_name: "DiscussionEntry", foreign_key: "root_entry_id"
has_many :discussion_subentries, -> { order(:created_at) }, class_name: "DiscussionEntry", foreign_key: "parent_id"
has_many :unordered_discussion_subentries, class_name: "DiscussionEntry", foreign_key: "parent_id"
has_many :flattened_discussion_subentries, class_name: "DiscussionEntry", foreign_key: "root_entry_id"
has_many :legacy_subentries, class_name: "DiscussionEntry", foreign_key: "parent_id", inverse_of: :parent_entry
has_many :root_discussion_replies, -> { where("parent_id=root_entry_id") }, class_name: "DiscussionEntry", foreign_key: "root_entry_id", inverse_of: :root_entry
has_many :discussion_subentries, -> { order(:created_at) }, class_name: "DiscussionEntry", foreign_key: "parent_id", inverse_of: :parent_entry
has_many :unordered_discussion_subentries, class_name: "DiscussionEntry", foreign_key: "parent_id", inverse_of: :parent_entry
has_many :flattened_discussion_subentries, class_name: "DiscussionEntry", foreign_key: "root_entry_id", inverse_of: :root_entry
has_many :discussion_entry_participants
has_one :last_discussion_subentry, -> { order(created_at: :desc) }, class_name: "DiscussionEntry", foreign_key: "root_entry_id"
has_one :last_discussion_subentry, -> { order(created_at: :desc) }, class_name: "DiscussionEntry", foreign_key: "root_entry_id", inverse_of: :root_entry
belongs_to :discussion_topic, inverse_of: :discussion_entries
belongs_to :quoted_entry, class_name: "DiscussionEntry"
# null if a root entry
belongs_to :parent_entry, class_name: "DiscussionEntry", foreign_key: :parent_id
belongs_to :parent_entry, class_name: "DiscussionEntry", foreign_key: :parent_id, inverse_of: :discussion_subentries
# also null if a root entry
belongs_to :root_entry, class_name: "DiscussionEntry"
belongs_to :user

View File

@ -85,7 +85,7 @@ class DiscussionTopic < ActiveRecord::Base
belongs_to :root_topic, class_name: "DiscussionTopic"
belongs_to :group_category
has_many :sub_assignments, through: :assignment
has_many :child_topics, class_name: "DiscussionTopic", foreign_key: :root_topic_id, dependent: :destroy
has_many :child_topics, class_name: "DiscussionTopic", foreign_key: :root_topic_id, dependent: :destroy, inverse_of: :root_topic
has_many :discussion_topic_participants, dependent: :destroy
has_many :discussion_entry_participants, through: :discussion_entries
has_many :discussion_topic_section_visibilities,

View File

@ -45,8 +45,8 @@ class Enrollment < ActiveRecord::Base
has_one :enrollment_state, dependent: :destroy, inverse_of: :enrollment
has_many :role_overrides, as: :context, inverse_of: :context
has_many :pseudonyms, primary_key: :user_id, foreign_key: :user_id
has_many :course_account_associations, foreign_key: "course_id", primary_key: "course_id"
has_many :pseudonyms, primary_key: :user_id, foreign_key: :user_id, inverse_of: false
has_many :course_account_associations, foreign_key: "course_id", primary_key: "course_id", inverse_of: false
has_many :scores, -> { active }
validates :user_id, :course_id, :type, :root_account_id, :course_section_id, :workflow_state, :role_id, presence: true

View File

@ -38,8 +38,8 @@ class Folder < ActiveRecord::Base
has_many :file_attachments, class_name: "Attachment"
has_many :active_file_attachments, -> { where("attachments.file_state<>'deleted'") }, class_name: "Attachment"
has_many :visible_file_attachments, -> { where(file_state: ["available", "public"]) }, class_name: "Attachment"
has_many :sub_folders, class_name: "Folder", foreign_key: "parent_folder_id", dependent: :destroy
has_many :active_sub_folders, -> { where("folders.workflow_state<>'deleted'") }, class_name: "Folder", foreign_key: "parent_folder_id", dependent: :destroy
has_many :sub_folders, class_name: "Folder", foreign_key: "parent_folder_id", dependent: :destroy, inverse_of: :parent_folder
has_many :active_sub_folders, -> { where("folders.workflow_state<>'deleted'") }, class_name: "Folder", foreign_key: "parent_folder_id", dependent: :destroy, inverse_of: :parent_folder
acts_as_list scope: :parent_folder

View File

@ -29,7 +29,7 @@ class LearningOutcomeGroup < ActiveRecord::Base
belongs_to :source_outcome_group, class_name: "LearningOutcomeGroup", inverse_of: :destination_outcome_groups
has_many :destination_outcome_groups, class_name: "LearningOutcomeGroup", inverse_of: :source_outcome_group, dependent: :nullify
has_many :child_outcome_groups, class_name: "LearningOutcomeGroup"
has_many :child_outcome_links, -> { where(tag_type: "learning_outcome_association", content_type: "LearningOutcome") }, class_name: "ContentTag", as: :associated_asset
has_many :child_outcome_links, -> { where(tag_type: "learning_outcome_association", content_type: "LearningOutcome") }, class_name: "ContentTag", as: :associated_asset, inverse_of: :associated_asset
belongs_to :context, polymorphic: [:account, :course]
before_save :infer_defaults

View File

@ -23,7 +23,7 @@ class LearningOutcomeResult < ActiveRecord::Base
belongs_to :user
belongs_to :learning_outcome
belongs_to :alignment, class_name: "ContentTag", foreign_key: :content_tag_id
belongs_to :alignment, class_name: "ContentTag", foreign_key: :content_tag_id, inverse_of: :learning_outcome_results
belongs_to :association_object,
polymorphic:
[:rubric_association,

View File

@ -32,7 +32,8 @@ class ModeratedGrading::ProvisionalGrade < ActiveRecord::Base
has_many :rubric_assessments, as: :artifact
has_one :selection,
class_name: "ModeratedGrading::Selection",
foreign_key: :selected_provisional_grade_id
foreign_key: :selected_provisional_grade_id,
inverse_of: :provisional_grade
belongs_to :source_provisional_grade, class_name: "ModeratedGrading::ProvisionalGrade"

View File

@ -20,7 +20,8 @@
class ModeratedGrading::Selection < ActiveRecord::Base
belongs_to :provisional_grade,
foreign_key: :selected_provisional_grade_id,
class_name: "ModeratedGrading::ProvisionalGrade"
class_name: "ModeratedGrading::ProvisionalGrade",
inverse_of: :selection
belongs_to :assignment, inverse_of: :moderated_grading_selections, class_name: "AbstractAssignment"
belongs_to :student, class_name: "User"

View File

@ -18,7 +18,7 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
class SharedBrandConfig < ActiveRecord::Base
belongs_to :brand_config, foreign_key: "brand_config_md5"
belongs_to :brand_config, foreign_key: "brand_config_md5", inverse_of: :shared_brand_configs
belongs_to :account
validates :brand_config, presence: true

View File

@ -19,7 +19,7 @@
#
class StudentEnrollment < Enrollment
belongs_to :student, foreign_key: :user_id, class_name: "User"
belongs_to :student, foreign_key: :user_id, class_name: "User", inverse_of: false
has_many :course_paces, through: :student

View File

@ -19,7 +19,7 @@
#
class Thumbnail < ActiveRecord::Base
belongs_to :attachment, foreign_key: "parent_id"
belongs_to :attachment, foreign_key: "parent_id", inverse_of: :thumbnails
# the ":keep_profile => true" part is in here so that we tell mini_magic to not try to pass the command line option -strip.
# this is because on the servers we are actually using graphics_magic not image_magic's mogrify and graphics_magick doesn't

View File

@ -91,7 +91,7 @@ class User < ActiveRecord::Base
has_many :not_ended_enrollments, -> { where("enrollments.workflow_state NOT IN ('rejected', 'completed', 'deleted', 'inactive')") }, class_name: "Enrollment", multishard: true
has_many :not_removed_enrollments, -> { where.not(workflow_state: %w[rejected deleted inactive]) }, class_name: "Enrollment", multishard: true
has_many :observer_enrollments
has_many :observee_enrollments, foreign_key: :associated_user_id, class_name: "ObserverEnrollment"
has_many :observee_enrollments, foreign_key: :associated_user_id, class_name: "ObserverEnrollment", inverse_of: :associated_user
has_many :observer_pairing_codes, -> { where("workflow_state<>'deleted' AND expires_at > ?", Time.zone.now) }, dependent: :destroy, inverse_of: :user
@ -192,8 +192,8 @@ class User < ActiveRecord::Base
has_many :learning_outcome_results
has_many :collaborators
has_many :collaborations, -> { preload(:user, :collaborators) }, through: :collaborators
has_many :assigned_submission_assessments, -> { preload(:user, submission: :assignment) }, class_name: "AssessmentRequest", foreign_key: "assessor_id"
has_many :assigned_assessments, class_name: "AssessmentRequest", foreign_key: "assessor_id"
has_many :assigned_submission_assessments, -> { preload(:user, submission: :assignment) }, class_name: "AssessmentRequest", foreign_key: "assessor_id", inverse_of: :assessor
has_many :assigned_assessments, class_name: "AssessmentRequest", foreign_key: "assessor_id", inverse_of: :assessor
has_many :web_conference_participants
has_many :web_conferences, through: :web_conference_participants
has_many :account_users

View File

@ -132,6 +132,8 @@ module CanvasRails
config.logger.formatter = ContextFormatter.new(config.logger.formatter)
end
config.active_record.automatic_scope_inversing = true
# Activate observers that should always be running
config.active_record.observers = %i[cacher stream_item_cache live_events_observer]

View File

@ -1104,7 +1104,7 @@ describe PlannerController do
assign_json = json_parse(response.body).find { |j| j["plannable_id"] == @assignment.id && j["plannable_type"] == "assignment" }
expect(assign_json["new_activity"]).to be true
submission.mark_item_read("comment")
submission.reload.mark_item_read("comment")
get :index, params: { start_date: @start_date, end_date: @end_date }
assign_json = json_parse(response.body).find { |j| j["plannable_id"] == @assignment.id && j["plannable_type"] == "assignment" }
expect(assign_json["new_activity"]).to be false

View File

@ -1786,6 +1786,9 @@ describe Account do
end
@sub2.save!
@account.reload
@sub1.reload
@sub2.reload
@settings.each do |key|
expect(@account.send(key)).to eq({ locked: false, value: false })
expect(@sub1.send(key)).to eq({ locked: true, value: true })
@ -1804,6 +1807,9 @@ describe Account do
end
@sub2.save!
@account.reload
@sub1.reload
@sub2.reload
@settings.each do |key|
expect(@account.send(key)).to eq({ locked: false, value: true })
expect(@sub1.send(key)).to eq({ locked: false, value: true, inherited: true })
@ -1831,22 +1837,22 @@ describe Account do
it "elides an empty setting" do
@sub1.update settings: { sis_assignment_name_length_input: { value: "" } }
expect(@sub1.sis_assignment_name_length_input).to eq({ value: "100", inherited: true })
expect(@sub1.reload.sis_assignment_name_length_input).to eq({ value: "100", inherited: true })
end
it "elides a nil setting" do
@sub1.update settings: { sis_assignment_name_length_input: { value: nil } }
expect(@sub1.sis_assignment_name_length_input).to eq({ value: "100", inherited: true })
expect(@sub1.reload.sis_assignment_name_length_input).to eq({ value: "100", inherited: true })
end
it "elides an explicitly-unlocked setting" do
@sub1.update settings: { sis_assignment_name_length_input: { value: nil, locked: false } }
expect(@sub1.sis_assignment_name_length_input).to eq({ value: "100", inherited: true })
expect(@sub1.reload.sis_assignment_name_length_input).to eq({ value: "100", inherited: true })
end
it "doesn't elide a locked setting" do
@sub1.update settings: { sis_assignment_name_length_input: { value: nil, locked: true } }
expect(@sub2.sis_assignment_name_length_input).to eq({ value: nil, inherited: true, locked: true })
expect(@sub2.reload.sis_assignment_name_length_input).to eq({ value: nil, inherited: true, locked: true })
end
end
@ -2805,10 +2811,10 @@ describe Account do
end
it "returns correct filters for each account level" do
expect(account4.available_ip_filters.size).to eq(3)
expect(account3.available_ip_filters.size).to eq(3)
expect(account2.available_ip_filters.size).to eq(2)
expect(account1.available_ip_filters.size).to eq(1)
expect(account4.reload.available_ip_filters.size).to eq(3)
expect(account3.reload.available_ip_filters.size).to eq(3)
expect(account2.reload.available_ip_filters.size).to eq(2)
expect(account1.reload.available_ip_filters.size).to eq(1)
end
end
end

View File

@ -4376,6 +4376,7 @@ describe Course do
end
def csv_output(include_final_grade_overrides: true)
@ase.each(&:reload)
@course.generate_grade_publishing_csv_output(
@ase,
@user,
@ -4468,6 +4469,7 @@ describe Course do
end
def csv_output
@ase.each(&:reload)
@course.generate_grade_publishing_csv_output(@ase, @user, @pseudonym)
end

View File

@ -43,7 +43,7 @@ describe Csp do
it "inherits settings" do
@root.enable_csp!
@accounts.each do |a|
expect(a.csp_enabled?).to be true
expect(a.reload.csp_enabled?).to be true
expect(a.csp_account_id).to eq @root.global_id
end
end
@ -51,7 +51,7 @@ describe Csp do
it "overrides inherited settings if explicitly set down the chain" do
@root.enable_csp!
@sub1.disable_csp!
expect(@sub2.csp_enabled?).to be false
expect(@sub2.reload.csp_enabled?).to be false
end
it "does not override inherited settings if explicitly set down the chain but locked" do
@ -59,7 +59,7 @@ describe Csp do
@sub1.disable_csp!
@root.lock_csp!
@accounts.each do |a|
expect(a.csp_enabled?).to be true
expect(a.reload.csp_enabled?).to be true
expect(a.csp_account_id).to eq @root.global_id
end
end

View File

@ -57,7 +57,7 @@ describe GroupMembership do
group.group_memberships.create!(user: user_model, workflow_state: "accepted")
group.group_memberships.create!(user: user_model, workflow_state: "accepted")
# expect
membership = group.group_memberships.build(user: user_model, workflow_state: "accepted")
membership = group.reload.group_memberships.build(user: user_model, workflow_state: "accepted")
expect(membership).not_to be_valid
expect(membership.errors[:group_id]).to eq ["The group is full."]
end

View File

@ -451,25 +451,25 @@ describe Group do
context "#full?" do
it "returns true when category group_limit has been met" do
@group.group_category = @course.group_categories.build(name: "foo")
@group.group_category.group_limit = 1
@group.group_category = @course.group_categories.build(name: "foo", group_limit: 1)
@group.add_user user_model, "accepted"
@group.association(:participating_users).reset
expect(@group).to be_full
end
it "returns true when max_membership has been met" do
@group.group_category = @course.group_categories.build(name: "foo")
@group.group_category.group_limit = 0
@group.group_category = @course.group_categories.build(name: "foo", group_limit: 0)
@group.max_membership = 1
@group.add_user user_model, "accepted"
@group.association(:participating_users).reset
expect(@group).to be_full
end
it "returns false when max_membership has not been met" do
@group.group_category = @course.group_categories.build(name: "foo")
@group.group_category.group_limit = 0
@group.group_category = @course.group_categories.build(name: "foo", group_limit: 0)
@group.max_membership = 2
@group.add_user user_model, "accepted"
@group.association(:participating_users).reset
expect(@group).not_to be_full
end
@ -477,9 +477,9 @@ describe Group do
# no category
expect(@group).not_to be_full
# not full
@group.group_category = @course.group_categories.build(name: "foo")
@group.group_category.group_limit = 2
@group.group_category = @course.group_categories.build(name: "foo", group_limit: 2)
@group.add_user user_model, "accepted"
@group.association(:participating_users).reset
expect(@group).not_to be_full
end
end

View File

@ -38,12 +38,12 @@ describe LiveAssessments::Submission do
# we can probably create a meaningful result with no points
# possible, but we don't now so that's what we test
submission.possible = 0
submission.create_outcome_result(alignment)
submission.create_outcome_result(alignment.reload)
expect(alignment.learning_outcome_results.count).to eq 0
end
it "creates an outcome result" do
submission.create_outcome_result(alignment)
submission.create_outcome_result(alignment.reload)
result = alignment.learning_outcome_results.first
expect(result).not_to be_nil
expect(result.title).to eq "#{assessment_user.name}, #{assessment.title}"
@ -57,7 +57,7 @@ describe LiveAssessments::Submission do
end
it "updates an existing outcome result" do
submission.create_outcome_result(alignment)
submission.create_outcome_result(alignment.reload)
result = alignment.learning_outcome_results.first
expect(result.percent).to eq 0.5
submission.score = 80
@ -68,7 +68,7 @@ describe LiveAssessments::Submission do
end
it "restores a deleted outcome result" do
submission.create_outcome_result(alignment)
submission.create_outcome_result(alignment.reload)
result = alignment.learning_outcome_results.first
result.destroy
submission.score = 80
@ -80,7 +80,7 @@ describe LiveAssessments::Submission do
it "scales the score to the outcome rubric criterion if present" do
outcome.data = { rubric_criterion: { mastery_points: 3, points_possible: 5 } }
outcome.save!
submission.create_outcome_result(alignment)
submission.create_outcome_result(alignment.reload)
result = alignment.learning_outcome_results.first
expect(result.percent).to eq 0.5
expect(result.score).to eq 2.5
@ -90,7 +90,7 @@ describe LiveAssessments::Submission do
it "sets mastery based on percent passed" do
alignment.mastery_score = 0.6
alignment.save!
submission.create_outcome_result(alignment)
submission.create_outcome_result(alignment.reload)
result = alignment.learning_outcome_results.first
expect(result.mastery).to be_falsey
submission.score = 80

View File

@ -273,7 +273,7 @@ RSpec.describe SubmissionComment do
@assignment.ensure_post_policy(post_manually: true)
@assignment.hide_submissions(submission_ids: [@submission.id])
@comment = @submission.add_comment(author: @teacher, comment: "some comment")
@comment = @submission.reload.add_comment(author: @teacher, comment: "some comment")
expect(@comment.messages_sent.keys).not_to include("Submission Comment")
end

View File

@ -7319,23 +7319,23 @@ describe Submission do
end
it "shows teacher all comments" do
comments = @submission.visible_submission_comments_for(@teacher)
comments = @submission.reload.visible_submission_comments_for(@teacher)
expect(comments).to match_array([@student_comment, @teacher_comment, @first_ta_comment])
end
it "shows ta all comments" do
comments = @submission.visible_submission_comments_for(@first_ta)
comments = @submission.reload.visible_submission_comments_for(@first_ta)
expect(comments).to match_array([@student_comment, @teacher_comment, @first_ta_comment])
end
it "shows student all comments, when submission is posted" do
@submission.update!(posted_at: Time.zone.now)
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments).to match_array([@student_comment, @teacher_comment, @first_ta_comment])
end
it "shows student only their own comment, when submission is unposted" do
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments).to match_array([@student_comment])
end
@ -7368,12 +7368,12 @@ describe Submission do
end
it "shows the submitting student their own comments and any peer review comments" do
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments).to match_array([@peer_review_comment, @student_comment, @alternate_assessment_comment])
end
it "shows a peer-reviewing student only their own comments" do
comments = @submission.visible_submission_comments_for(@student2)
comments = @submission.reload.visible_submission_comments_for(@student2)
expect(comments).to match_array([@peer_review_comment])
end
end
@ -7384,12 +7384,12 @@ describe Submission do
end
it "shows the submitting student comments from all users" do
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments).to match_array([@peer_review_comment, @student_comment, @teacher_comment])
end
it "shows a peer-reviewing student only their own comments" do
comments = @submission.visible_submission_comments_for(@student2)
comments = @submission.reload.visible_submission_comments_for(@student2)
expect(comments).to match_array([@peer_review_comment])
end
end
@ -7414,7 +7414,7 @@ describe Submission do
end
it "returns comments scoped to that group" do
comments = @submission.visible_submission_comments_for(@teacher)
comments = @submission.reload.visible_submission_comments_for(@teacher)
expect(comments).to match_array([@student_comment, @student2_comment])
end
@ -7444,17 +7444,17 @@ describe Submission do
end
it "shows a peer reviewer only their own comments" do
comments = @submission.visible_submission_comments_for(@student2)
comments = @submission.reload.visible_submission_comments_for(@student2)
expect(comments).to match_array([@peer_review_comment])
end
it "shows all comments to the submitting student" do
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments).to match_array([@peer_review_comment, @student_comment, @teacher_comment])
end
it "shows all comments to a teacher" do
comments = @submission.visible_submission_comments_for(@teacher)
comments = @submission.reload.visible_submission_comments_for(@teacher)
expect(comments).to match_array([@peer_review_comment, @student_comment, @teacher_comment])
end
end
@ -7556,7 +7556,7 @@ describe Submission do
context "when graders can view other graders' comments" do
context "when grades are unpublished" do
it "shows final grader all submission comments" do
comments = @submission.visible_submission_comments_for(@teacher)
comments = @submission.reload.visible_submission_comments_for(@teacher)
expect(comments).to match_array([
@student_comment,
@first_ta_comment,
@ -7567,7 +7567,7 @@ describe Submission do
end
it "shows provisional grader all submission comments" do
comments = @submission.visible_submission_comments_for(@first_ta)
comments = @submission.reload.visible_submission_comments_for(@first_ta)
expect(comments).to match_array([
@student_comment,
@first_ta_comment,
@ -7578,12 +7578,12 @@ describe Submission do
end
it "shows student only their own comments" do
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments).to match_array([@student_comment])
end
it "shows admins all submission comments" do
comments = @submission.visible_submission_comments_for(@admin)
comments = @submission.reload.visible_submission_comments_for(@admin)
expect(comments).to match_array([
@student_comment,
@first_ta_comment,
@ -7602,7 +7602,7 @@ describe Submission do
end
it "shows final grader all submission comments" do
comments = @submission.visible_submission_comments_for(@teacher)
comments = @submission.reload.visible_submission_comments_for(@teacher)
expect(comments.pluck(:comment)).to match_array([
"Student comment",
"First Ta comment",
@ -7613,7 +7613,7 @@ describe Submission do
end
it "shows provisional grader all submission comments" do
comments = @submission.visible_submission_comments_for(@first_ta)
comments = @submission.reload.visible_submission_comments_for(@first_ta)
expect(comments.pluck(:comment)).to match_array([
"Student comment",
"First Ta comment",
@ -7624,13 +7624,13 @@ describe Submission do
end
it "shows student only their own comments" do
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments).to match_array([@student_comment])
end
it "when grades are posted, shows student their own, chosen grader's, and final grader's comments" do
@assignment.post_submissions
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments.pluck(:comment)).to match_array([
"Student comment",
"First Ta comment",
@ -7639,7 +7639,7 @@ describe Submission do
end
it "shows admins all submission comments" do
comments = @submission.visible_submission_comments_for(@admin)
comments = @submission.reload.visible_submission_comments_for(@admin)
expect(comments.pluck(:comment)).to match_array([
"Student comment",
"First Ta comment",
@ -7658,7 +7658,7 @@ describe Submission do
context "when grades are unpublished" do
it "shows final grader all submission comments" do
comments = @submission.visible_submission_comments_for(@teacher)
comments = @submission.reload.visible_submission_comments_for(@teacher)
expect(comments).to match_array([
@student_comment,
@first_ta_comment,
@ -7669,17 +7669,17 @@ describe Submission do
end
it "shows provisional grader their own and student's" do
comments = @submission.visible_submission_comments_for(@second_ta)
comments = @submission.reload.visible_submission_comments_for(@second_ta)
expect(comments.pluck(:comment)).to match_array(["Student comment", "Second Ta comment"])
end
it "shows student only their own comments" do
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments).to match_array([@student_comment])
end
it "shows admins all submission comments" do
comments = @submission.visible_submission_comments_for(@admin)
comments = @submission.reload.visible_submission_comments_for(@admin)
expect(comments).to match_array([
@student_comment,
@first_ta_comment,
@ -7698,7 +7698,7 @@ describe Submission do
end
it "shows final grader all submission comments" do
comments = @submission.visible_submission_comments_for(@teacher)
comments = @submission.reload.visible_submission_comments_for(@teacher)
expect(comments.pluck(:comment)).to match_array([
"Student comment",
"First Ta comment",
@ -7709,7 +7709,7 @@ describe Submission do
end
it "shows provisional grader their own, student's, chosen grader's, and final grader's comments" do
comments = @submission.visible_submission_comments_for(@second_ta)
comments = @submission.reload.visible_submission_comments_for(@second_ta)
expect(comments.pluck(:comment)).to match_array([
"Student comment",
"First Ta comment",
@ -7719,13 +7719,13 @@ describe Submission do
end
it "shows student only their own comments" do
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments).to match_array([@student_comment])
end
it "when grades are posted, shows student own, chosen grader's, and final grader's comments" do
@assignment.post_submissions
comments = @submission.visible_submission_comments_for(@student)
comments = @submission.reload.visible_submission_comments_for(@student)
expect(comments.pluck(:comment)).to match_array([
"Student comment",
"First Ta comment",
@ -7734,7 +7734,7 @@ describe Submission do
end
it "shows admins all submission comments" do
comments = @submission.visible_submission_comments_for(@admin)
comments = @submission.reload.visible_submission_comments_for(@admin)
expect(comments.pluck(:comment)).to match_array([
"Student comment",
"First Ta comment",