This way, when the language is written form right-to-left, elements
using Foundation mixins/classes will float to the opposite direction as
they do in left-to-right languages. The same will apply to text
alignment.
To offer full support for RTL languages, we need to change every single
reference to `float: left`, `float: right`, `text-align: left`,
`text-align: right`, and possible adjust other properties like `left`,
`margin-left`, `padding-left` or `border-left`. In the meantime, we at
least partially support these languages.
Replacing `float` with `flex` when possible would also improve RTL
support.
The spinner was added in version 2.0.0, so by disabling it we're keeping
the behavior we've got in existing CONSUL installations.
The problem with the spinner is installations need to add a secret token
and share it across instances (when they've got more than one), and if
they don't, invisible captcha might report false positives.
I guess we could use `Rails.application.secrets.secret_key_base` as
secret token, but since we haven't tested this feature at all, it's
better to disable it for now.
Our `namespace` helper returns a string. However, Rails version 5.2.4.6
doesn't allow strings as arguments to polymorphic_path [1]
Since returning a symbol in our `namespace` helper would break other
places in the application, we're converting it to a symbol in the
methods calling `polymorphic_path`.
[1] https://github.com/advisories/GHSA-hjg4-8q5f-x6fm
Pronto is an external tool which is use to check code conventions and is
not needed to run the application, just like rubocop or scss-lint.
Loading it caused a couple of issues. First, it loaded BetterHtml, and
we had to disable it in order to avoid crashes in the development
environment.
Second, it loaded ruby-progressbar, which loads the ProgressBar class,
which conflicts with our own ProgressBar class. This made the
application crash whenever the ProgressBar class was used.
This way developers can run the checks on their machines and using
`bundle exec` we guarantee the right versions of all our gems are being
used; with Hound we can only use the versions supported by their
service.
When including the pronto-erb_lint gem, we're getting errors in
development where our ERB does not follow the conventions Better HTML
expects. Since we only use Better HTML because ERB Lint depends on it,
and right now we are not ready to follow its conventions, we're
disabling it.
Note pronto depends on rugged, which requires CMake and pkg-config to
build the `libgit2` library it depends on. CMake and pkg-config are
installed by default in some GNU/Linux distributions like Ubuntu, but
might not be installed on other systems, so we're adding them as
development dependencies.
We were using a custom icon because in the past social-share-button
didn't have support for whatsapp. But now that it does, we can remove
our custom icon.
Note we're using the `_app` suffix because that's the name of the icon
meant for mobile devices.
Note we're adding the icons in English on both the `sdg/en/` folder and
the `sdg/default/` folder. The latter stores the default icons when the
desired language does not have a fallback with an icon folder.
Also note we need to explicitely add the images to the asset pipeline
because they've been added to the `vendor/` folder; for some reason,
everything works properly without adding them to the asset pipeline if
we use the `app/` folder instead.
We do a similar thing with the settings helper, caching settings on a
per-request basis.
Using an instance variable in a helper reduces the amount of times we
need to calculate the cache key during a single request.
Even if Rails caches SQL queries per request, the test suite is faster
with this change, and we get rid of many redundant queries in the logs.
This way we avoid fetching each translation every time it's requested.
This reduces the amount of queries in the development logs and also
makes the test suite faster.
Since data for this model (title and description) is not generated in
CONSUL but by the United Nations, we aren't storing it in the database
but in our YAML translation files.
The reasoning is as follows. Suppose that, a few months after CONSUL
gets SDG support, a new language is added to CONSUL.
With YAML files, getting the texts in the new language would mean
updating CONSUL to include the new language.
But if we store these texts in the database, it means we have to update
the databases of all existing CONSUL installations, either each
installation by themselves (duplicating efforts) or running a rake task
(which we would have to write each time).
So we believe using translations works better in this case.
We're still storing records in the database with the code, so they can
be easily referenced via `has_many` or `has_many :through` associations.
The original devise_security_extension gem has not been maintained for
years. Its last release was version 0.10.0, and wasn't compatible with
Rails 5, and so we were using its master branch.
Since the gem was unmaintained, it was forked as devise-security and the
aforementioned master branch was released as version 0.10.1. This
version wasn't published in Rubygems, though, so we're now using the
first version that was published in Rubygems and had a release
announment [1].
Dependabot will probably open a pull request to upgrade to the latest
version, but for now I'm trying to keep the devise-security gem as
similar as the version we were using to make sure they're compatible,
particularly considering we're monkey-patching some of the modules
provided by this gem.
[1] https://github.com/devise-security/devise-security/releases/tag/v0.11.1
While Rails provides a lot of functionality by default, there's one
missing piece which is present in frameworks like Django or Phoenix: the
so-called "view models", or "components".
It isn't easy to extract methods in a standard Rails view/partial, since
extracting them to a helper will make them available to all views, and
so two helper methods can't have the same name. It's also hard to
organize the code in modules, and due to that it's hard to figure out
where a certain helper method is supposed to be called from.
Furthermore, object-oriented techniques like inheritance can't be
applied, and so in CONSUL customizing views is harder that customizing
models.
Components fix all these issues, and work the way Ruby objects usually
do.
Components are also a pattern whose popularity has increased a lot in
the last few years, with JavaScript frameworks like React using them
heavily. While React's components aren't exactly the same as the
components we're going to use, the concept is really similar.
I've always liked the idea of components. However, there wasn't a stable
gem we could safely use. The most popular gem (cells) hasn't been
maintained for years, and we have to be very careful choosing which gems
CONSUL should depend on.
The view_component gem is maintained by GitHub, which is as a guarantee
of future maintenance as it can be (not counting the Rails core team),
and its usage started growing after RailsConf 2019. While that's
certainly not a huge amount of time, it's not that we're using an
experimental gem either.
There's currently a conflict between view_component and wicked_pdf.
We're adding a monkey-patch with the fix until it's merged in
wicked_pdf.
We can remove the `new_framework_defaults_5_2` file by using Rails 5.2
default options and overwriting the ones we haven't enabled.
We're disabling `use_authenticated_message_encryption` because, even if
we don't use it, some CONSUL installations might be using it, and
enabling this options would make it harder to decrypt existing encrypted
messages.
And we're disabling `cache_versioning` until we verify our cache keeps
working and expires as expected on production environments, particularly
for stats.
This is enabled by default in Rails 5.2 applications.
Note this change will cause all fragment caching to expire. We consider
it acceptable considering the page where caching is most important
(stats) is barely affected by this change, since this change only
affects the view, and the time-consuming operations are cached in the
model.
Comments are actually affected, though, and pages with thousands of
comments might take a few extra seconds to load the first time they're
accessed after this change. We don't think this is going to be an issue
on existing CONSUL installations.
This is the default encryption for cookies in Rails 5.2 applications.
The reason it isn't enabled automatically for existing applications is
these cookies are not compatible with running the application on several
servers when some of them use Rails 4. Since this isn't our case (we
don't support using different versions of CONSUL on different servers),
and existing cookies are still read correctly, we can safely enable it.
We were manually adding forgery protection to all our controllers, but
in Rails 5.2 there's an option (enabled by default for new applications)
which adds this protection to all controllers.
Even if we don't use form_with, it makes sense to configure it to behave
the same way form_for does.
This is the default option in Rails 5.2 applications. IMHO it should
have been the default option for Rails 5.1 too, since generally form
inputs need an ID so they can easily be associated with a label.
All the code in the `bin/` and the `config/` folder has been generated
running `rake app:update`, except the `escape_javascript_fix` file,
which we've removed since the code there is already included in Rails
5.2.
We were checking tho project_id but not the project_key. However, in our
example secrets file we actually include a project_id but not a
project_key, and so new CONSUL installations would crash in production
environments.
Although technically the application doesn't crash if no host is
defined, we're also ignoring the current environment if no host is
defined, since errbit/airbrake is unlikely to work in this scenario.
Since some people hosting errbit might be using it as an internal tool
with a self signed certificate, we need to patch Airbrake so it accepts
these certificates.
With Errbit, you can set up your own server and host the information
regarding your exceptions there. You can also hire Airbrake's hosting
services or easily setup Errbit on Heroku.
We're still including the rollbar gem so we don't harm CONSUL users who
are using rollbar.
Note Errbit requires an old version of Airbrake which forced users to
configure the gem. So we're adding the current environtment to
`ignore_environments` when the project id isn't defined; this way the
application won't crash in this case.
Using pg_search 2.0.1 with Rails 5.2 results in deprecation warnings:
DEPRECATION WARNING: Dangerous query method (method whose arguments used
as raw SQL) called with non-attribute argument(s):
"pg_search_978c2f8941354cf552831b.rank DESC, \"tags\".\"id\" ASC".
Non-attribute arguments will be disallowed in Rails 6.0. This method
should not be called with user-provided values, such as request
parameters or model attributes. Known-safe values can be passed by
wrapping them in Arel.sql().
We're not upgrading to the latest pg_search because it only supports
ActiveRecord >= 5.2.
Using `pluck("DISTINCT")` was raising a warning in Rails 5.2:
DEPRECATION WARNING: Dangerous query method (method whose arguments are
used as raw SQL) called with non-attribute argument(s): "DISTINCT
taggings.tag_id". Non-attribute arguments will be disallowed in Rails
6.0. This method should not be called with user-provided values, such as
request parameters or model attributes. Known-safe values can be passed
by wrapping them in Arel.sql().
Since there was only one other use of distinct, I've decided to change
both of them in the same commit, even if the second one wasn't raising a
warning.
These columns were causing Rails 5.2 to throw a warning when ordering by
them, as if they weren't valid column names:
DEPRECATION WARNING: Dangerous query method (method whose arguments are
used as raw SQL) called with non-attribute argument(s):
:"budget/investments_count". Non-attribute arguments will be disallowed
in Rails 6.0. This method should not be called with user-provided
values, such as request parameters or model attributes. Known-safe
values can be passed by wrapping them in Arel.sql().
This change also makes their names consistent with the rest of our
tables and columns.
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.
Recent versions introduce the `Layout/SpaceAroundMethodCallOperator`,
which we are going to use. We aren't upgrading to the latest rubocop
version because it conflicts with the version of Capybara we're using
and because it isn't supported by Hound.
Some rules have been renamed:
Layout/IndentAssignment is now Layout/AssignmentIndentation
Layout/IndentHeredoc is now Layout/HeredocIndentation
Layout/LeadingBlankLines is now Layout/LeadingEmptyLines
Layout/Tab is now Layout/IndentationStyle
Layout/TrailingBlankLines is now Layout/TrailingEmptyLines
Lint/StringConversionInInterpolation is now Lint/RedundantStringCoercion
Metrics/LineLength is now Layout/LineLength
Note after upgrading we get a new "offense" in the `StartWith` rule, so
we're changing the code in order to fix it.
These routes are solved in a different way because of an inconsistency:
we define `groups` and `budget_investments`; we should either use the
`budget_` prefix in all places or remove it everywhere.
We can now share code using `polymorphic_path` even with these models.
In the past, we couldn't use `polymorphic_path` in many places. For
instance, `polymorphic_path(budget, investment)` would return
`budget_budget_investment_path`, while in our routes we had defined
`budget_investment_path`.
With the `resolve` method, introduced in Rails 5.1, we can use symbols
to define we want it to use `investment` instead of `budget_investment`.
It also works with nested resources, so now we can write
`polymorphic_path(investment)`.
This makes the code for `resource_hierarchy_for` almost impossible to
understand. I reached this result after having a look at the internals
of the `resolve` method in order to get its results and then remove the
symbols we include.
Note using this method will not make admin routes compatible with
`polymorphic_path`. Quoting from the Rails documentation:
> This custom behavior only applies to simple polymorphic URLs where a
> single model instance is passed and not more complicated forms, e.g:
> [example showing admin routes won't work]
Also note that now the `admin_polymorphic_path` method will not work for
every model due to inconsistencies in our admin routes. For instance, we
define `groups` and `budget_investments`; we should either use the
`budget_` prefix in all places or remove it everywhere. Right now the
code only works for items with the prefix; it isn't a big deal because
we never call it with an item without the prefix.
Finally, for unknown reasons some routing tests fail if we use
`polymorphic_path`, so we need to redefine that method in those tests
and force the `only_path: true` option.
This plugin provides more control over tables and solves a JS error thrown
when user clicks on "Cell properties" ckeditor feature.
https://ckeditor.com/cke4/addon/tabletools
All of these plugins are not used anywhere.
Change introduced at ckeditor initializer will ommit unneeded
precompilation of plugins assets on production environments.
Change introduced at ckeditor config file adresses the problem with assets
pipeline fallback on testing environments described here: #2711. Now plugins
that are explicitly disabled will not be precomiled when running ckeditor
javascript enabled feature specs.
While this is not a secret and in theory should be in a file under
version control, currently the CONSUL installer disables delayed jobs by
default, meaning we were keeping two versions of the delayed jobs
configuration file, and some existing configurations have their settings
defined in a file in capistrano's `shared` folder.
So we're moving existing settings to the secrets file.