All the code in the `bin/` and the `config/` folders has been generated
running `rake app:update`. The only exception is the code in
`config/application.rb` where we've excluded the engines that Rails 6.0
has added, since we don't use them.
There are a few changes in Active Storage which aren't compatible with
the code we were using until now.
Since the method to assign an attachment in ActiveStorage has changed
and is incompatible with the hack we used to allow assigning `nil`
attachments, and since ActiveStorage now supports assigning `nil`
attachments, we're removing the mentioned hack. This makes the
HasAttachment module redundant, so we're removing it.
Another change in ActiveStorage is files are no longer saved before
saving the `ActiveStorage::Attachment` record. This means we need to
manually upload the file when using direct uploads. We also have to
change the width and height validations we used for images; however,
doing so results in very complex code, and we currently have to write
that code for both images and site customization images.
So, for now, we're just uploading the file before checking its
dimensions. Not ideal, though. We might use active_storage_validations
in the future to fix this issue (when they support a proc/lambda, as
mentioned in commit 600f5c35e).
We also need to update a couple of tests due to a small change in
response headers. Now the content disposition returns something like:
```
attachment; filename="budget_investments.csv"; filename*=UTF-8''budget_investments.csv
```
So we're updating regular expression we use to check the filename.
Finally, Rails 6.0.1 changed the way the host is set in integration
tests [1] and so both `Capybara.app_host` and `Capybara.default_host`
were ignored when generating URLs in the relationable examples. The only
way I've found to make it work is to explicitely assign the host to the
integration session. Rails 6.1 will change this setup again, so maybe
then we can remove this hack.
[1] https://github.com/rails/rails/pull/36283/commits/fe00711e9
The current consul GraphQL API has two problems.
1) It uses some unnecessary complicated magic to automatically create
the GraphQL types and querys using an `api.yml` file. This approach
is over-engineered, complex and has no benefits. It's just harder to
understand the code for people which are not familiar with the
project (like me, lol).
2) It uses a deprecated DSL [1] that is soon going to be removed from
`graphql-ruby` completely. We are already seeing deprecation warning
because of this (see References).
There was one problem. I wanted to create the API so that it is fully
backwards compatible with the old one, BUT the old one uses field names
which are directly derived from the ruby code, which results in
snake_case field names - not the GraphQL way. When I'm using the
graphql-ruby Class-based syntax, it automatically creates the fields in
camelCase, which breaks backwards-compatibility.
So I've added deprecated snake_case field names to keep it
backwards-compatible.
[1] https://graphql-ruby.org/schema/class_based_api.html
We are use a display: block style for labels containing check boxes inside
them, and the label has a width of 100%.
This means that clicking on the blank space on the right of the label text
will check/uncheck the checkbox. To avoid this behaviour we modify the
"display" attribute of the labels.
In order to prevent unexpected behaviour in terms_of_service form labels,
we add specific css for this case when define a checkbox within the
.actions class.
The application crashed when we generated hints to attributes with
interpolation arguments in their `human_attribute_name`.
When generating the hint, we used the `custom_label` method to generate
a label and get the `for` attribute and, since we weren't passing a
text, it used the default human attribute name for the field. However,
it crashes if the default attribute name requires an interpolation
argument.
So now, since we were only using the `custom_label` method in order to
get the `for` attribute, we're simply passing an arbitrary text to the
method.
We were getting a warning in Rails 6:
DEPRECATION WARNING: ActionView::Base instances should be constructed
with a lookup context, assignments, and a controller.
We were using this hack in order to allow `File.new` attachments in
tests files. However, we can use the `fixture_file_upload` helper
instead.
Just like it happened with `file_fixture`, this helper method doesn't
work in fixtures, so in this case we're using `Rack::Test::UploadedFile`
instead.
This way we don't have to write `"spec/fixtures/files"` every time.
Note this method isn't included in factories. We could include it like
so:
```
FactoryBot::SyntaxRunner.class_eval do
include ActiveSupport::Testing::FileFixtures
self.file_fixture_path = RSpec.configuration.file_fixture_path
end
```
However, I'm not sure about the possible side effects, and since we only
use attachments in a few factories, there isn't much gain in applying
the monkey-patch.
This fixes a few issues we've had for years.
First, when attaching an image and then sending a form with validation
errors, the image preview would not be rendered when the form was
displayed once again. Now it's rendered as expected.
Second, when attaching an image, removing it, and attaching a new
one, browsers were displaying the image preview of the first one. That's
because Paperclip generated the same URL from both files (as they both
had the same hash data and prefix). Browsers usually cache images and
render the cached image when getting the same URL.
Since now we're storing each image in a different Blob, the images have
different URLs and so the preview of the second one is correctly
displayed.
Finally, when users downloaded a document, they were getting files with
a very long hexadecimal hash as filename. Now they get the original
filename.
The `parameterize` method uses the `I18n.transliterate` method, whose
documentation says:
```
I18n.transliterate("Ærøskøbing")
=> "AEroskobing"
I18n.transliterate("日本語")
=> "???"
```
That means we can't use it for dictionaries where characters don't have
a transliteration to the latin alphabet.
So we're changing the code in order to only transliterate characters
with a transliteration to the latin alphabet.
Note the first example ("Česká republika") already worked with the
previous code; the test has been added to make sure accented characters
are handled properly.
This way we don't have to use the `send` method in other places, like
the AdminNotification class, and we can change the internal
implementation at any point.
We're going to add geozones as user segments, so it's handy to have the
method in the UserSegments class.
We're also changing the `user_segment_emails` parameter name for
consistency and simplicity.
There could be inconsistencies in the database and an attachment might
have a `record_id` pointing to a record which no longer exist. We were
getting an exception in this case.
Just like we add the `storage_` prefix for new records so we can use
both Active Storage and Paperclip at the same time.
Now the migration actually works, at least for basic cases.
`dalli_store` is deprecated since dalli 2.7.11.
We can now enable cache_versioning. We didn't enable it when upgrading
to Rails 5.2 because of possible incompatibility with `dalli_store` [1],
even though apparently some the issues were fixed in dalli 2.7.9 and
dalli 2.7.10 [2].
Since using cache versioning makes cache expiration more efficient, and
I'm not sure whether the options we were passing to the dalli store are
valid with memcache store (documentation here is a bit lacking), I'm
just removing the option we used to double the default cache size on
production.
[1] https://www.schneems.com/2018/10/17/cache-invalidation-complexity-rails-52-and-dalli-cache-store
[2] https://github.com/petergoldstein/dalli/blob/master/History.md
Since version 2.0 introduced many breaking changes, we're upgrading to
it first.
The changes have been done by installing the rubocop-faker gem and
running:
```
rubocop \
--require rubocop-faker \
--only Faker/DeprecatedArguments \
--auto-correct
```
Our previous system to delete cached attachments didn't work for
documents because the `custom_hash_data` is different for files created
from a file and files created from cached attachments.
When creating a document attachment, the name of the file is taken into
account to calculate the hash. Let's say the original file name is
"logo.pdf", and the generated hash is "123456". The cached attachment
will be "123456.pdf", so the generated hash using the cached attachment
will be something different, like "28af3". So the file that will be
removed will be "28af3.pdf", and not "123456.pdf", which will still be
present.
Furthermore, there are times where users choose a file and then they
close the browser or go to a different page. In those cases, we weren't
deleting the cached attachments either.
So we're adding a rake task to delete these files once a day. This way
we can simplify the logic we were using to destroy cached attachments.
Note there's related a bug in documents: when editing a record (for
example, a proposal), if the title of the document changes, its hash
changes, and so it will be impossible to generate a link to that
document. Changing the way this hash is generated is not an option
because it would break links to existing files. We'll try to fix it when
moving to Active Storage.
When we assigned `I18n.available_locales = default_locales` in the
`ensure` block, `I18n.locale` was set to `:zh-TW`, which is not one of
the default locales.
In some cases this resulted in tests failing:
```
I18n::InvalidLocale:
:"zh-TW" is not a valid locale
```
Note we're making the validation rule dynamic so it's affected by the
way we stub the constant in the tests to emulate data created in old
applications.
Co-Authored-By: Javi Martín <javim@elretirao.net>
So tests won't fail when an institution changes the default organization
name.
The tests are also easier to understand now, since it's more obvious
where the "CONSUL" text is coming from.
By using real XML responses developers will be able to understand better
how the integration works (the data flow), and the correspondency between
`remote_census` settings and their place at a real XML response.
As `stubbed_responses` methods were removed from the model layer now the
stubbing part should be managed from the test environment code so also
added a new helper module `RemoteCensusSetup` that can be used anywhere
where we need to call the web service.
Co-Authored-By: Javi Martín <javim@elretirao.net>
By simplyfing the responses the configuration for specs can be simpler too.
We're also using more generic terms instead of the ones used in Madrid's
Census API.
Co-Authored-By: Javi Martín <javim@elretirao.net>
Otherwise the variants returned for document_type="1" and
document_number="" will be
`["0", "00", "000", "0000", "00000", "000000", "0000000", "00000000"]`
which seems to be useless.
Probably this case is not real for production environments where those
arguments will always be fullfilled but seems to be interesting for
testing environment where this method is being called when those
paremeters where empty.
This rule was added in Rubocop 0.91.0. A similar rule named
LeakyConstantDeclaration was added in rubocop-rspec 1.34.0.
Note using the FILENAMES constant did not result in an offense using the
ConstantDefinitionInBlock rule but did result in an offense using the
LeakyConstantDeclaration rule. I've simplified the code to get rid of
the constant; not sure why we were adding a constant with `||=` in the
middle of a spec.
Rails 5.2 crashes in the `db:create` task because it tries to run the
`after_initialize` block before the database is created.
The easiest way to solve it is to move the code out of the initializer
and calculate the API type definitions on demand. Note results are still
cached using a class instance variable (not to be confused with a class
variable), and so once definitions are obtained, they will remain
constant until the application is restarted, even in the development
environment.