Note: to avoid confusion, "answer" will mean a row in the poll_answers
table and "choice" will mean whatever is in the "answer" column of that
table (I'm applying the same convention in the code of the task).
In order make this task perform reasonably on installations with
millions of votes, we're using `update_all` to update all the answers
with the same choice at once. In order to do that, we first need to
check the existing choices and what are the possible option_ids for
those choices.
Note that, in order for this task to work, we need to remote the
duplicate answers first. Otherwise, we will run into a RecordNotUnique
exception when trying to add the same option_id to two duplicate
answers.
So we're making this task depend on the one that removes duplicate
answers. That means we no longer need to specify the task to remove
duplicate answers in the release tasks; it will automatically be
executed when running the task to add an option_id.
Until now, we've stored the text of the answer somebody replied to. The
idea was to handle the scenarios where the user voters for an option but
then that option is deleted and restored, or the texts of the options
are accidentally edited and so the option "Yes" is now "Now" and vice
versa.
However, since commit 3a6e99cb8, options can no longer be edited once
the poll starts, so there's no risk of the option changing once somebody
has voted.
This means we can now store the ID of the option that has been voted.
That'll also help us deal with a bug introduced int 673ec075e, since
answers in different locales are not counted as the same answer. Note we
aren't dealing with this bug right now.
We're still keeping (and storing) the answer as well. There are two
reasons for that.
First, we might add an "open answer" type of questions in the future and
use this column for it.
Second, we've still got logic depending on the answer, and we need to be
careful when changing it because there are existing installations where
the answer is present but the option_id is not.
Note that we're using `dependent: nullify`. The reasoning is that, since
we're storing both the option_id and the answer text, we can still use
the answer text when removing the option. In practice, this won't matter
much, though, since we've got a validation rule that makes it impossible
to destroy options once the poll has started.
Also note we're still allowing duplicate records when the option is nil.
We need to do that until we've removed every duplicate record in the
database.
It was confusing to have the action to create an answer in
`QuestionsController#answer` while the action to destroy it was
`AnswersController#destroy`.
The routes for poll questions were accidentally deleted in commit
5bb831e959 when deleting the `:show` action, and restored in commit
9871503c5e. However, the deleted code was:
```
resources :questions, only: [:show], controller: 'polls/questions' (...)
```
While the restored code was:
```
resources :questions, controller: 'polls/questions' (...)
```
Meaning we forgot to add the `only: []` option when restoring the
routes.
We also forgot to remove the `before_action` code when deleting the
`:show` action, so we're removing it now.
Note that, since poll answers belong to a user and not to a voter, we
aren't doing anything regarding poll answers. This is a separate topic
that might be dealt with in a separate pull request.
Also note that, since there are no records belonging to poll voters, and
poll voters don't use `acts_as_paranoia` and don't have any callbacks on
destroy, it doesn't really matter whether we call `destroy!` or
`delete`. We're using `delete` so there are no unintended side-effects
that might affect voters with the same `user_id` and `poll_id` on
Consul Democracy installations customizing this behavior.
Note that, when taking votes from an erased user, since poll answers
don't belong to poll voters, we were not migrating them in the
`take_votes_from` method (and we aren't migrating them now either).
This call was added in commit 81f65f1ac, and the test for its need was
added in commit cb1542874. However, both the test and the helper method
relying on the `touch` call were removed in commit f90d0d9c4.
We were checking we didn't have more votes than allowed in the case of
questions with multiple answers, but we weren't checking it in the case
of questions with a single answer. This made it possible to create more
than one answer to the same question. This could happen because the
method `find_or_initialize_user_answer` might initialize two answers in
different threads, due to a race condition.
Most existing Consul Democracy installations will have changed their
`config.i18n.available_locales` option so only a few locales are
available. In many cases, only one locale will be available. In these
cases, rendering a form that only offers one option is useless.
We've considered adding a text in this case mentioning that, in order to
enable more languages, they need to configure their
`config.i18n.available_locales`. However, we haven't done it for two
reasons.
First, if they've changed the available locales to just one, there's a
good chance they aren't interested at all in configuring the locales.
And, second, if there's only one available locale, administrators will
learn to ignore the "languages" link, so they won't realize that locales
can be configured if developers change the available locales. If we hide
the link, on the other hand, they will notice that locales can now be
configured once developers change the available locales.
Note we're still allowing access by entering the URL. This is harmless,
though, since people accessing it this way will see a form with only one
possible option and won't be able to modify anything.
We were using `authorize_resource`, passing it an unnamed parameter.
When that happens, CanCanCan only checks permissions to read that
resource. But, in this case, we want to check the permission to update
that resource before the `update` action.
Most of the time, it doesn't really matter, but, for example, in our
demo we're going to restrict the locales configuration so locales cannot
be updated on the main tenant (but they can be updated on other
tenants).
This way we'll notice syntax inconsistencies in pull requests. We
weren't doing it until now because there's no Pronto runner for MDL and
we weren't running linters individually.
Note we aren't checking the templates in the `.github` folders, since
these templates don't have a top level header in the beginning (they'll
be displayed on a page which already has a top level header) and MDL
doesn't provide a way to ignore certain rules on certain files. So we're
specifying which files to include instead of running `mdl .` (which
would also include the `node_modules` folder) or running `mdl -g .`
(which would exclude the `node_modules` folder but would include the
`.github` folder).
We aren't following this rule in the `docs/es/features/graphql.md` file
because we need to specify the HTML ID attribute of an element (since by
default markdown generates IDs based on the text, and the text contains
accented letters).
Ideally we would simply ignore this rule on this file, but it isn't
currently possible with Markdownlint, so, until we find a better
solution, we're removing this rule.
We've considered keeping the rule and using heading IDs like:
```
## Características {#caracteristicas}
```
However, this syntax isn't supported by every application rendering
markdown. For instance, github doesn't support it, and we're aiming to
have a documentation that can be read on either github or gitbook.
We were following it about half of the time and we even added it to our
former `.mdlrc` file. However, for some reason, MDL doesn't detect this
rule when specified in the `.mdlrc` file, so we didn't notice we weren't
following it in many cases.
Now that we're using a style file to configure MDL, we can enable this
rule again and apply it, since now MDL correctly includes it in its
report.
Not sure whether it's a good idea to end a heading with a question mark.
When in doubt, we usually keep the code as it is now, so that's what
we're doing.
This way we'll be able to customize some of the rules, which doesn't
seem to be possible when using the `.mdlrc` file.
For simplification purposes, instead of including all rules one by one,
we're excluding the few rules we don't use.
Since the page contains an <h1> tag (the title of the issue), the main
headings of this file should be level 2 headings.
We're removing the "How" section in the flaky specs template for
simplicity (and because we usually don't use this template at all).
Note that MDL reports that the first heading should be a level 1
heading, but, as mentioned earlier, this doesn't make sense in the
context of a github issue. We'll probably exclude these files from MDL
checks in order to avoid this issue.
These files are essentially the same as our README files, only our
README files contain information that only makes sense in the context
of a repository.
On GitBook, currently Spanish and English belong in different spaces, so
we're going to provide two different github integrations (one per
language).
So we're using a different SUMMARY.md file per language.
For consistency, since there was a link to the README file in the
Spanish summary, we're also adding it to the English one. It was working
in any case because on our current gitbook page the summary was
generated through gitbook.
Since we no longer have any of the files referenced in the
`.gitbook.yaml` file, we're removing it as well.
Note that there was a typo in the English summary, which pointed to the
Spanish license. It didn't matter, though, since the license file is
actually in English in both cases.
These files were both in the Consul Democracy repository and the
documentation repository. Since now both repositories have been merged
into one, we can remove the duplicate files.
Note there was a small difference in the `.mdlrc` file because we
changed it in commit b3a718ae6. We're keeping this change so we don't
get these syntax warnings in the documentation.