There's nothing magic about Rubocop, but it does encourage you think about what makes readable (as opposed to just correct) code. In this case, I think it is clearer to make the conditions explicit in the rating method as you've done rather than break them up into separate methods to pass Rubocop. Specifically, I would suggest this:
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
# rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
def rating
case
when response_quality == 1 && @typos.zero?
5
when response_quality == 2 && @typos.zero?
4
when response_quality == 3 && @typos.zero?
3
when @typos.percent_of(@word_length) < 20
2
when @typos.percent_of(@word_length) < 30
1
when @typos.percent_of(@word_length) > 30
0
end
end
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
Finally, you should consider whether you want rating
to be nil
when no conditions match, and you might consider explicitly adding an else nil
to make that decision obvious.