Upgrade guide
We'll update this page when we release new Avo 3 versions.
If you're looking for the Avo 2 to Avo 3 upgrade guide, please visit the dedicated page.
Upgrade from 3.5.4 to 3.5.5
-> Record errors
With version 3.5.5
we introduced a stricter error check. Now when the record have any error included the action will fail. This allow you to do things like:
before_update do
if validation_fail?
errors.add(:field_id, "Error message")
end
end
Upgrade from 3.4.2 to 3.4.3
-> turbo
configuration
In version 3.4.2
we introduced turbo configuration with instantclick
option. We decided that instant_click
is a more appropriate name.
config.turbo = {
instantclick: true
instant_click: true
}
Upgrade from 3.4.1 to 3.4.2
-> Basic Filters URL param changed to encoded_filters
When we added the Dynamic Filters feature, by mistake we introduced a bug where you couldn't use the Basic and Dynamic Filters together because they are both using the filters
URL param.
This is not what we intended.
To fix this we are changing the URL param of the Basic Filters from filters
to encoded_filters
so now you can have a URL with both filters.
# Before
https://example.com/avo/resources/users?filters[first_name][contains][]=Jason&page=1&filters=eyJBdm86OkZpbHRlcnM6OklzQWRtaW4iOlsiYWRtaW5zIl19
# After
https://example.com/avo/resources/users?filters[first_name][contains][]=Jason&page=1&encoded_filters=eyJBdm86OkZpbHRlcnM6OklzQWRtaW4iOlsiYWRtaW5zIl19
What to do?
If you have hardcoded links where you reference the filters
param, change that to encoded_filters
. These links might be in Tools, Resource Tools, Menu Items, or regular view partials (yes, basically anywhere you might have added them 🫤).
A quick search through your codebase should reveal them.
-> Add active_record_extended
gem to your Gemfile
In order to extend Avo's filtering capabilities for arrays and tags fields, we use the active_record_extended
gem.
This gem uses postgres and was breaking for those who use any other database like sqlite
.
If you want to keep Contained in
option on arrays and tags filters you should include the active_record_extended
gem to your Gemfile
.
-> Multiple action flux
First iteration of multiple action flux was using redirect_to
with turbo_frame: "actions_show"
. With the update to turbo 8 the redirect was giving some troubles and we decided that is time to improve this experience with a proper response type, navigate_to_action
.
If you have a multiple action flux implemented with redirect_to
you should change it to navigate_to_action
.
-> Action link_arguments
method
Action link_arguments
method handles the arguments
encoding and encryption internally now so you only need to pass the arguments
as a hash and the returned path
will already include the encoded arguments.
field :name,
as: :text,
filterable: true,
name: "name (click to edit)",
only_on: :index do
arguments = Base64.encode64 Avo::Services::EncryptionService.encrypt(
message: {
cities: Array[resource.record.id],
render_name: true
},
purpose: :action_arguments
)
arguments = {
cities: Array[resource.record.id],
render_name: true
}
path, data = Avo::Actions::City::Update.link_arguments(
resource: resource,
arguments: arguments
)
link_to resource.record.name, path, data: data
end
-> resource.record
or record
as nil
on visibility blocks
You may notice that resource.record == nil
on some visibility blocks. That happens when evaluating the field visibility to render header columns. On index, there is no record.
This is a consequence of a bug fix where resource.record
was wrongly storing the last record of the index table.
Check this discussion for more details
Upgrade from 3.3.0 to 3.4.0
Ruby 3.0 is end-of-life and we pushed some code that only works with Ruby 3.1.
Upgrade from 3.2.2 to 3.3.0
-> may_download_file
deprecated
Actions now fully operate with turbo leading to the deprecation of may_download_file
option. It can be safely removed from all actions.
-> Status field failed_when
and loading_when
default to and empty array
We found some issues with declaring defaults to failed_when
and loading_when
field options so we are now defaulting them to empty arrays.
If you need that behavior back, add it to your fields.
field :status,
as: :status,
failed_when: [:failed],
loading_when: [:waiting, :running]
-> Scopes namespace change
Scopes changed namespace from Avo::Pro::Scopes
to Avo::Advanced::Scopes
.
-> TailwindCSS integration
The symlink generated by avo:sym_link
task was renamed from tmp/avo/base.css
to tmp/avo/avo.base.css
. If your application has the TailwindCSS integration generated before Avo 3.3.0
you should replace @import '../../../../tmp/avo/base.css';
with '../../../../tmp/avo/avo.base.css';
in app/assets/stylesheets/avo/avo.tailwind.css
.
/* app/assets/stylesheets/avo/avo.tailwind.css */
@import '../../../../tmp/avo/base.css'; // [!code --]
@import '../../../../tmp/avo/avo.base.css';
Upgrade from 3.1.3 to 3.1.4
-> Avo::Filters::BaseFilter.decode_filters
We removed the rescue that would return {}
on parsing error. This rescue block was occasionally concealing pertinent errors. Ensure that when invoking Avo::Filters::BaseFilter.decode_filters
the argument is not nil
and has been encoded using the Avo::Filters::BaseFilter.encode_filters
method.
Upgrade from 3.0.1.beta24 to 3.0.2
-> Sidebar should be declared inside a panel
We introduced the main_panel
option and also refactored the way that fields are fetched from the resource, now we allow multiple sidebars per panel but each sidebar should be defined inside a panel
or main_panel
block.
We suggest to read panels and sidebars sections for more information and to be aware of the new possibilities.
-> Dashboards visibility and authorization
Previously, if the visible
attribute was set to false
on dashboards, visiting them was impossible because the controller would trigger a "Not found" error. In cases where authorize
returned false
, the controller would block access but still keep the dashboard visible.
This behavior has been enhanced. Now, even if visible
is set to false
, the dashboard remains accessible but won't appear in the menu. Additionally, if authorize
returns false
, the dashboards are now hidden.
-> Actions
We've internally implemented some changes around actions to resolve certain bugs. No action is needed from your end, but if you happen to notice any anomalies in the actions flow, please get in touch with us so we can address them promptly. Thank you.
-> Attachments eager load
Attachments are no longer automatically eager loading. If you want to eager load attachments there are at least two ways:
Use self.includes
option
class Avo::Resources::PhotoComment < Avo::BaseResource
self.includes = [:user, [photo_attachment: :blob]]
def fields
field :user, as: :belongs_to
field :photo, as: :file, is_image: true
end
Use self.index_query
option
class Avo::Resources::Product < Avo::BaseResource
self.index_query = -> {
query.includes image_attachment: :blob
}
def fields
field :image, as: :file, is_image: true
end
Upgrade from 3.0.1.beta23 to 3.0.1.beta24
-> Cards
With the new feature that allow cards on resources we've realized that it's no longer logical to retain cards within the Dashboard
namespace scope. Consequently, each card is now located within the Avo::Cards
namespace.
# Before
class Avo::Cards::AmountRaised < Avo::Dashboards::MetricCard
class Avo::Cards::ExampleAreaChart < Avo::Dashboards::ChartkickCard
class Avo::Cards::ExampleBarChart < Avo::Dashboards::ChartkickCard
# ...
# After
class Avo::Cards::AmountRaised < Avo::Cards::MetricCard
class Avo::Cards::ExampleAreaChart < Avo::Cards::ChartkickCard
class Avo::Cards::ExampleBarChart < Avo::Cards::ChartkickCard
# ...
Upgrade from 3.0.1.beta22 to 3.0.1.beta23
-> Caching
Since there are many available cache stores and we were allowing only few we changed the way of computing the cache store to be used by Avo.
One of our concerns was to maintain the status quo, but if you notice any caching issues there is a new configurable option config.cache_store
that allows you to tell Avo what cache_store
to use.
Check cache page for more details.
Upgrade from 3.0.1.beta8 to 3.0.1.beta9
-> Heading as field
Heading option changed declaration mode, one of the main reasons for this change is to be able to generate a clear data-field-id
on the DOM
For more information about heading
field syntax check heading
field's documentation.
heading "personal information"
heading "contact"
heading '<div class="underline uppercase font-bold">DEV</div>', as_html: true
field :personal_information, as: :heading # data-field-id == "personal_information"
field :heading, as: :heading, label: "Contact" # data-field-id == "heading"
field :dev, as: :heading, as_html: true, label: '<div class="underline uppercase font-bold">DEV</div>'
-> Badge field secondary
option renamed to neutral
We believe that the term neutral
better reflects the intended use.
field :stage,
as: :badge,
options: {
info: [:discovery, :idea],
success: :done,
warning: "on hold",
danger: :cancelled,
secondary: :drafting
}
field :stage,
as: :badge,
options: {
info: [:discovery, :idea],
success: :done,
warning: "on hold",
danger: :cancelled,
neutral: :drafting
}
-> Rename link_to_resource
to link_to_record
link_to_resource
was renamed to link_to_record
.
class Avo::Resources::User < Avo::BaseResource
def fields
field :id, as: :id, link_to_resource: true
field :email, as: :gravatar, link_to_resource: true
end
end
class Avo::Resources::User < Avo::BaseResource
def fields
field :id, as: :id, link_to_record: true
field :email, as: :gravatar, link_to_record: true
end
end
Upgrade from 3.0.1.beta5 to 3.0.1.beta6
-> The status field changed behavior
Before, for the status you'd set the failed
and loading
states and everything else fell under success
. That felt unnatural. We needed a neutral
state. Now we changed the field so you'll set the failed
, loading
, and success
values and the rest fall under neutral
.
# Before
field :status,
as: :status,
failed_when: :failed,
loading_when: :loading
# After
field :status,
as: :status,
failed_when: :failed,
loading_when: :loading
success_when: :deployed # specify the success state