Having exceptions is better than having silent bugs.
There are a few methods I've kept the same way they were.
The `RelatedContentScore#score_with_opposite` method is a bit peculiar:
it creates scores for both itself and the opposite related content,
which means the opposite related content will try to create the same
scores as well.
We've already got a test to check `Budget::Ballot#add_investment` when
creating a line fails ("Edge case voting a non-elegible investment").
Finally, the method `User#send_oauth_confirmation_instructions` doesn't
update the record when the email address isn't already present, leading
to the test "Try to register with the email of an already existing user,
when an unconfirmed email was provided by oauth" fo fail if we raise an
exception for an invalid user. That's because updating a user's email
doesn't update the database automatically, but instead a confirmation
email is sent.
There are also a few false positives for classes which don't have bang
methods (like the GraphQL classes) or destroying attachments.
For these reasons, I'm adding the rule with a "Refactor" severity,
meaning it's a rule we can break if necessary.
Using arrays made it difficult to order by more than one field (like the
`most_voted` scope does), and so we were ordering by `confidence_score`
and ignoring the `created_at` column.
Using an AR relation makes it easy to reuse the existing `most_voted`
scope.
This change has one side effect: now comments with equal votes are
ordered in descending order instead of having no specific order. That
means flaky specs which failed sometimes because they assumed comments
were ordered by date are now always green.
I've also re-added the `oldest` scope removed in 792b15b thinking it was
removed because using it with arrays was too hard.
Using `setseed` and ordering by `RAND()` doesn't always return the same
results because, although the generated random numbers will always be
the same, PostgreSQL doesn't guarantee the order of the rows it will
apply those random numbers to, similar to the way it doesn't guarantee
an order when the `ORDER BY` clause isn't specified.
Using something like `reorder("legislation_proposals.id % #{seed}")`,
like we do in budget investments, is certainly more elegant but it makes
the test checking two users get different results fail sometimes, so
that approach might need some adjustments in order to make the results
more random.
Using a number with only two decimals means the seed is going to be the
same 1% of the time. Using ruby's default value for random numbers makes
it almost impossible to generate the same seed twice.
Using `rand` also simplifies the code, and it's what we use in the
budget investments controller.
Just like it's done everywhere else in the application. Not doing so
means users who aren't logged in receive a "you aren't authorized"
message when they try to create a new legislation proposal instead of
being redirected to the login page.