avo
avo copied to clipboard
Default settings
Context
We want to give the ability to developers to set certain settings to a certain value globally.
For example, set all the belongs_to fields to have the searchable value to true.
Explorations
config.default_settings = {
fields: {
belongs_to: {
searchable: false,
polymorphic_as: false,
relation_method: false,
}
},
"fields.belongs_to.searchable": false,
"fields.belongs_to.polymorphic_as": false,
"fields.belongs_to.relation_method": false,
}
@searchable = default_attribute("fields.belongs_to.searchable", args[:searchable] == true)
@polymorphic_as = default_attribute("fields.belongs_to.polymorphic_as", args[:can_create].nil? ? true : args[:can_create])
def default_attribute(key, default)
if value_exists?(key)
value(key)
else
default
end
end
Possible approaches (none of the code was executed/tested):
1. Merge defaults on boot
- Create a hash for each field defaults, let's take an example on
Avo::Fields::BelongsTo
BELONGS_TO_DEFAULTS = {
searchable: false,
can_create: true
}
- Collect user defaults for that field (to be decided where and how)
USER_BELONGS_TO_DEFAULTS = {
searchable: true,
can_create: true
}
-
On boot merge options and override avo defaults with user defaults:
BELONGS_TO_DEFAULTS.merge!(USER_BELONGS_TO_DEFAULTS) -
Use the merged defaults hash to access default values:
def initialize(id, **args, &block)
# ...
@searchable = args[:searchable].nil? ? BELONGS_TO_DEFAULTS[:searchable] : args[:searchable]
@can_create = args[:can_create].nil? ? BELONGS_TO_DEFAULTS[:can_create] : args[:can_create]
# ...
end
- Optional: DRY refactor
def initialize(id, **args, &block)
# ...
initialize_option :searchable, args
initialize_option :can_create, args
# ...
end
def initialize_option(option, args)
user_option = args.dig(option)
instance_variable_set(:"@#{option}", user_option.nil? ? BELONGS_TO_DEFAULTS.dig(option) : user_option)
end
2. Check for user default on each initialize
- Collect user defaults for that field (to be decided where and how)
USER_BELONGS_TO_DEFAULTS = {
searchable: true,
can_create: true
}
- When user option is not provided check for user defaults first then apply avo defaults if not present
def initialize(id, **args, &block)
# ...
@searchable = if args[:searchable].nil?
user_default = USER_BELONGS_TO_DEFAULTS[:searchable]
user_default.nil? ? false : user_default
else
args[:searchable]
end
@can_create = if args[:can_create].nil?
user_default = USER_BELONGS_TO_DEFAULTS[:can_create]
user_default.nil? ? true : user_default
else
args[:can_create]
end
# ...
end
- Optional: DRY refactor
def initialize(id, **args, &block)
# ...
initialize_option :searchable, args
initialize_option :can_create, args
# ...
end
def initialize_option(option, args)
user_option = args.dig(option)
value = if user_option.nil?
user_default = USER_BELONGS_TO_DEFAULTS.dig(option)
user_default.nil? ? false : user_default
else
user_option
end
instance_variable_set(:"@#{option}", value)
end
Things to have in consideration
- Performance. We should identify the approach with less performance impact
- Presence checks. We should validate present by using
nil?method insteadpresent?because the presence method can returnfalseif the value is intentionally setted asfalseor empty. - Complexity. Lets ensure that the complexity of this mechanism is maintained as low as possible to preserve easy readability and maintainability
This issue has been marked as stale because there was no activity for the past 15 days.
As a current workaround the base resource can be extended and the field parser can be overridden
For example, if we want all the fields to have reloadable: true as default
module Avo
class BaseResource < Avo::Resources::Base
# Users can override this class to add custom methods for all resources.
def field(field_name, **args, &block)
super(field_name, **args.merge(reloadable: true), &block)
end
end
end