你在找什麼叫做「nil guard」。這有幾個方便的模式:
# safe navigation operator - if `nil_thing` is nil, `points` won't be called
nil_thing&.points
# the double ampersand check (what you've used)
if nil_thing && nil_thing.points == 100
# compound one-line conditional
do_stuff if nil_thing.points == 100 unless nil_thing.blank?
您也可避免這種情況很多的時間:
if student.scores.where(points: 100, assignment: team.assignment).exists?
do_stuff
end
注意,我們在裝配此查詢的方式使得它很難避免N + 1個查詢問題。
我懷疑你在學生和作業之間沒有適當的關係。我會重新命名Score
到StudentAssignment
,並在其上具有score
屬性:
class Student
has_many :student_assignments
has_many :assignments, through: :student_assignments
end
class Assignment
has_many :student_assignments
has_many :students, through: :student_assignments
end
然後你可以使用基本的預先加載和價值的比較在Ruby中:
Assignment.includes(student_assignments: :students).each do |assignment|
puts "Scores for #{assignment.name}:"
assignment.student_assignments.each do |sa|
puts "#{sa.student.name} scored #{sa.score}"
puts "Congratulations to #{sa.student.name}" if sa.score >= 99
end
end
您可以從另一個方向做以及:循環通過一名學生,並用分數顯示他們的作業。
如果您有一個安裝程序,無法將學生連接到多對多作業,則可以設置一個像perfect_scores
這樣的條件關聯,這樣可以讓您使用ActiveRecord關係熱切加載其他任意查詢導航避免N + 1:
class Student
has_many :scores
has_many :perfect_scores, -> { where(score: 100) }, class_name: 'Score', inverse_of: :student
def perfect_score_on_assignment?(assignment)
if perfect_scores.loaded?
# use cached data
perfect_scores.any? { |score| score.assignment_id == assignment.id }
else
# use sql to determine
perfect_scores.where(assignment: assignment).exists?
end
end
end
class Score
belongs_to: :student
belongs_to: :assignment
end
class Assignment
has_many :scores
end
# Load up all of the students and eager load perfect scores
@students = Student.includes(perfect_scores: :assignment)
@assignments = Assignment.all
@assignment.each do |assignment|
@students.each do |student|
if student.perfect_score_on_assignment?(assignment)
puts "#{student.name} scored 100%"
end
end
end
非常好。謝謝你的解答和你的回答。我有一個功能可以檢查每個學生的作業,因此它可以運行幾千次。你會建議哪種模式以獲得最佳性能? –
@JeffZivkovic剛剛更新了兩個鬆散的假設例子,如何處理這取決於你的情況。 – coreyward
現在,這超越了!我會嘗試將您的示例適用於我的應用程序。 –